【JUC】并发编程重点知识——乐观锁与悲观锁

目录

一、悲观锁

二、乐观锁

三、对比

四、选择场景



一、悲观锁

        悲观锁总是假设最坏的情况,认为共享资源每次被访问的时候就会出现问题(比如共享数据被修改),所以每次在获取资源操作的时候都会上锁,这样其他线程想拿到这个资源就会阻塞直到锁被上一个持有者释放。也就是说,共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程

核心思想:假设并发冲突必然发生,操作数据前先加锁,确保独占访问。

实现机制

synchronized关键字

  • JVM内置锁,自动加锁/释放锁

  • 修饰方法或代码块

public synchronized void update() { 
    // 操作共享资源
}

ReentrantLock显式锁

  • 需手动加锁/解锁

  • 提供更灵活的锁控制(可中断、公平锁等)

private final ReentrantLock lock = new ReentrantLock();
public void update() {
    lock.lock();
    try {
        // 操作共享资源
    } finally {
        lock.unlock();
    }
}

特点

  • 阻塞式:未获锁线程进入阻塞状态(BLOCKED)

  • 保证强一致性

  • 适用场景:

    • 写操作频繁(冲突概率高)

    • 临界区代码执行时间长

    • 需要严格数据一致性(如银行转账)

工作流程

二、乐观锁

       乐观锁总是假设最好的情况,认为共享资源每次被访问的时候不会出现问题,线程可以不停地执行,无需加锁也无需等待,只是在提交修改的时候去验证对应的资源(也就是数据)是否被其它线程修改了(具体方法可以使用版本号机制或 CAS 算法)。

核心思想:假设并发冲突较少,操作数据时不加锁,提交更新时检测冲突。

实现机制

CAS(Compare and Swap)

  • 原子指令:Unsafe类提供底层支持

  • Java封装类:AtomicIntegerAtomicReference

AtomicInteger atomicInt = new AtomicInteger(0);
public void update() {
    int oldValue, newValue;
    do {
        oldValue = atomicInt.get();
        newValue = oldValue + 1;
    } while (!atomicInt.compareAndSet(oldValue, newValue)); // 自旋重试
}

版本号机制

  • 数据库常用(如MySQL MVCC)

  • Java实现:AtomicStampedReference(解决ABA问题)

AtomicStampedReference<Integer> ref = new AtomicStampedReference<>(0, 0);
public void update() {
    int oldStamp, newStamp;
    Integer oldValue, newValue;
    do {
        oldValue = ref.getReference();
        oldStamp = ref.getStamp();
        newValue = oldValue + 1;
        newStamp = oldStamp + 1;
    } while (!ref.compareAndSet(oldValue, newValue, oldStamp, newStamp));
}

特点

  • 非阻塞:线程通过自旋重试(不进入阻塞状态)

  • 最终一致性

  • 适用场景:

    • 读多写少(冲突概率低)

    • 临界区代码执行时间短

    • 高并发读场景(如计数器、状态标志)

工作流程

三、对比

特性悲观锁乐观锁
加锁时机操作数据前加锁提交更新时检测冲突
线程状态阻塞(BLOCKED)自旋(RUNNABLE)
数据一致性强一致性最终一致性
实现复杂度简单需处理重试/ABA问题
性能开销上下文切换成本高CPU自旋消耗(冲突少时高效)
适用场景写多读少、长事务读多写少、短操作
典型实现synchronizedReentrantLockAtomicXXXStampedLock

四、选择场景

  • 选择悲观锁当

    • 临界区代码复杂或执行时间长

    • 写操作频率 > 读操作频率

    • 需要严格保证数据实时一致性(如支付系统)

  • 选择乐观锁当

    • 读操作频率远高于写操作(≥10:1)

    • 冲突概率低于20%

    • 追求高吞吐量(如电商库存计数)

    • 无法承受线程阻塞开销(实时系统)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值