DEV Community

Woody
Woody

Posted on

乐观锁Optimistic Lock 悲观锁 Pessimistic Lock 和 CAS

你问的三个概念——乐观锁(Optimistic Lock)悲观锁(Pessimistic Lock)CAS(Compare And Swap/Set)——都是并发控制和线程安全的核心机制,我给你系统地梳理一下,并且用例子和类比说明。


1️⃣ 悲观锁(Pessimistic Lock)

概念:悲观锁假设别人会同时修改你要操作的数据,所以在你操作数据之前,就先上锁,确保别人不能改,直到你完成操作后再释放锁。
特点

  • 保证数据安全,几乎不会出现冲突。
  • 代价是性能低,因为锁住期间其他线程必须等待。
  • 常见实现:synchronized(Java)、ReentrantLock、数据库中的行锁/表锁。

类比:你去图书馆借书,悲观锁就像你把书拿到手上,并锁在你的抽屉里,别人必须等你还书才能借。

Java 示例

class Counter {
    private int count = 0;

    public synchronized void increment() {
        count++;
    }

    public int getCount() {
        return count;
    }
}
Enter fullscreen mode Exit fullscreen mode

这里的 synchronized 就是悲观锁。


2️⃣ 乐观锁(Optimistic Lock)

概念:乐观锁假设别人不会同时修改你要操作的数据,在修改时检查一下数据是否被修改过,如果被修改过,则重试。
特点

  • 不加锁,性能好,适合读多写少的场景。
  • 实现依赖于版本号或者时间戳
  • 如果冲突发生,需要回退或者重试。

类比:你去图书馆借书,乐观锁就像你先拿书去借阅区看,拿去结账时发现别人已经借走了,你就重新选择其他书。

Java 示例(版本号实现)

class OptimisticCounter {
    private int count = 0;
    private int version = 0;

    public boolean increment() {
        int oldVersion = version;
        int oldCount = count;
        // 先假设没人修改
        int newCount = oldCount + 1;
        // 检查版本号
        if (oldVersion == version) {
            count = newCount;
            version++;
            return true;
        } else {
            return false; // 冲突,需要重试
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

3️⃣ CAS(Compare-And-Swap / Compare-And-Set)

概念:CAS 是一种原子操作,它的机制是:

比较内存中的值是否等于期望值,如果相等则更新为新值,否则不更新。
它是乐观锁的硬件级实现

特点

  • 无锁操作,提高性能。
  • 有 ABA 问题,需要额外手段处理(如版本号)。
  • JVM 的 AtomicInteger 就是用 CAS 实现的。

类比:你在ATM机上存钱:

  1. 你看到账户余额是 100。
  2. 你想存 10。
  3. 机器检查余额还是 100,如果是,就存 10;如果别人已经改成 110,就不操作,重试。

Java 示例(AtomicInteger)

import java.util.concurrent.atomic.AtomicInteger;

class CASCounter {
    private AtomicInteger count = new AtomicInteger(0);

    public void increment() {
        int oldValue;
        int newValue;
        do {
            oldValue = count.get();
            newValue = oldValue + 1;
        } while (!count.compareAndSet(oldValue, newValue));
    }

    public int getCount() {
        return count.get();
    }
}
Enter fullscreen mode Exit fullscreen mode

这里 compareAndSet 就是 CAS 操作。


🔹 总结对比

特性 悲观锁 乐观锁 CAS
锁类型 阻塞锁 无锁或版本号 原子操作
性能 较低
冲突处理 阻塞等待 检测失败重试 检测失败重试
适用场景 写多且冲突大 读多写少 高并发无锁场景

如果你愿意,我可以帮你画一张悲观锁 vs 乐观锁 vs CAS 的直观流程图,让你一眼就理解它们的差别。

你希望我画吗?

Top comments (0)