悲观锁是查询时加锁,然后下面的流程锁住,别的线程不可以访问,当前面的线程完成后释放锁,这是让线程同步了。那乐观锁,算同步吗,因为两个线程还是可以同时查询,只是修改时,version不对的会被打回?
算同步,但它是"不堵门的同步"。
你的观察非常准确——这是理解两种锁本质区别的关键。
同步 ≠ 必须阻塞等待
同步的本质是:协调多个线程对共享资源的访问,保证最终结果正确。
至于怎么协调,有两种思路:
| 悲观锁 | 乐观锁 | |
|---|---|---|
| 策略 | 先假设会冲突,提前堵门 | 先假设不会冲突,事后检查 |
| 协调方式 | 阻塞式同步— 没轮到的线程挂起等待 | 非阻塞式同步— 失败的线程自己重试或放弃 |
| 线程体验 | "都给我排队,一个一个来" | "你们都去试,撞车了自行解决" |
为什么乐观锁也算同步?
回到你的审核场景:
线程A查询 → 状态待审核,版本=1 线程B查询 → 状态待审核,版本=1 线程A提交 → UPDATE ... WHERE 版本=1 → 成功,版本变成2 线程B提交 → UPDATE ... WHERE 版本=1 → 失败(版本已经是2了)虽然 A 和 B同时查到了旧数据,但数据库最终只让一个线程修改成功。
这就是同步——系统通过版本号机制,在写操作这一步强制达成了"同一时刻只有一个线程能真正修改成功"的效果。
另一个线程被打回,要么重试(重新查询最新版本再改),要么直接报错退出。
一句话总结
悲观锁= 同步靠"保安堵门"(互斥)
乐观锁= 同步靠"事后对账"(冲突检测)
两者都解决了竞态条件,只是悲观锁在入口处排队,乐观锁在出口处筛选。最终都是让系统从"可能同时审核两次"变成"只会审核一次"。