面试:Java中乐观锁的实现原理是什么

乐观锁的基本概念

乐观锁是一种并发控制机制,假设多线程并发访问时不会发生冲突,因此在操作数据时不会加锁。只有在提交更新时才会检查数据是否被其他线程修改过。如果没有冲突,操作成功;否则,根据业务需求进行重试或抛出异常。

乐观锁的实现方式

在Java中,乐观锁通常通过版本号机制或CAS(Compare-And-Swap)操作实现。

版本号机制

版本号机制的核心是为数据增加一个版本号字段。每次更新数据时,版本号递增。提交更新时,检查当前版本号是否与读取时的版本号一致。

示例代码:

java 复制代码
public class OptimisticLockExample {
    private int version;

    public boolean updateWithVersion(int expectedVersion, int newValue) {
        if (this.version == expectedVersion) {
            this.version++;
            return true;
        }
        return false;
    }
}
CAS操作

CAS是一种无锁算法,通过比较当前值与预期值是否相等来决定是否更新。Java中的java.util.concurrent.atomic包提供了多个原子类(如AtomicIntegerAtomicReference),底层基于CAS实现。

示例代码:

java 复制代码
import java.util.concurrent.atomic.AtomicInteger;

public class CASExample {
    private AtomicInteger value = new AtomicInteger(0);

    public boolean increment() {
        int oldValue = value.get();
        return value.compareAndSet(oldValue, oldValue + 1);
    }
}

乐观锁的应用场景

乐观锁适用于读多写少的场景,冲突较少时性能优于悲观锁。常见的应用包括:

  • 数据库乐观锁(通过version字段)
  • 缓存更新
  • 无锁数据结构的实现

乐观锁的优缺点

优点:

  • 无锁操作,减少线程阻塞,提高并发性能
  • 避免死锁问题

缺点:

  • 冲突频繁时,重试开销大
  • 需要额外的字段或机制支持(如版本号)

数据库中的乐观锁实现

在数据库中,乐观锁通常通过WHERE条件结合版本号实现。例如:

sql 复制代码
UPDATE table_name 
SET column1 = new_value, version = version + 1 
WHERE id = target_id AND version = expected_version;

如果更新影响的行数为0,说明版本号不一致,操作失败。

相关推荐
karry_k6 小时前
MyBatis批量insert-select踩坑:useGeneratedKeys=true 可能让PostgreSQL返回大量插入结果
java·后端
karry_k6 小时前
PostgreSQL 在 MyBatis 中执行正常 SQL 失效:一次 DELETE USING 踩坑记录
java·后端
SamDeepThinking10 小时前
从源码到代码:MyBatis-Flex 与 MyBatis-Plus 的逐项对比
java·后端·程序员
用户8524950718410 小时前
解密 JavaScript 中的 this:谁才是真正的调用者?
javascript·面试
Heo10 小时前
Vite进阶用法详解
前端·javascript·面试
洛卡卡了10 小时前
Claude Code rules 要怎么用,团队协作时如何统一代码规范呢?
面试·agent·claude
她的男孩13 小时前
Spring Boot 接 Flowable 工作流:用 3 个注解搭一个请假审批流程
java·后端·架构
不好听61314 小时前
JavaScript 的 this 到底指向谁?
javascript·面试
烬羽14 小时前
面试官:聊聊 LocalStorage 和 this 指向?看这篇就够了
面试·程序员