HelloCoder HelloCoder
首页
《Java小白求职之路》
《小白学Java》
计算机毕设
  • 一些免费计算机资源
  • 脚手架工具
  • 《从0到1学习Java多线程》
  • 《从0到1搭建服务器》
  • 《可观测和监控》
随笔
关于作者
首页
《Java小白求职之路》
《小白学Java》
计算机毕设
  • 一些免费计算机资源
  • 脚手架工具
  • 《从0到1学习Java多线程》
  • 《从0到1搭建服务器》
  • 《可观测和监控》
随笔
关于作者
  • 《LearnJavaToFindAJob》

    • 导读

    • 【初级】6~12k档

    • 【中级】12k-26k档

      • JVM进阶

      • Java进阶

        • ConcurrentHashMap面试题
        • CopyOnWriteArrayList的实现原理
        • HashMap的put过程是怎么样的?
        • IO模型有哪些?
        • Synchronized相关
        • ThreadLocal的原理
        • synchronized锁升级
        • valueOf、(String)强转有什么区别?
        • 为什么在lambda中使用的局部变量必须是final或有效final
        • 你知道如何更新缓存吗?如何保证缓存和数据库双写一致性?
        • 八股文之ReentrantLock
        • 分布式事务
        • 可中断和不可中断锁
        • 如何保障生产端消息投递成功?
        • 如何手动触发全量回收垃圾,如何立即触发垃圾回收
        • 并发

        • 悲观锁和乐观锁
        • 数据库连接池为什么要使用ThreadLocal?
        • 线程池中多余的线程是如何回收的
        • 谈谈你对AQS的理解
        • 谈谈你对CAS的理解
        • util.concurrent的理解
        • 高并发下如何保证接口的幂等性?
      • MySQL

      • 中间件

      • 算法

      • 高阶

    • 【高级】26k+档

    • 大厂面试题

    • 求职建议

    • 面经

  • LearnJavaToFindAJob
  • 【中级】12k-26k档
  • Java进阶
#悲观锁 #乐观锁
HaC
2026-06-08
目录

悲观锁和乐观锁

# 一、悲观锁(Pessimistic Lock)

定义:悲观锁认为并发冲突一定会发生,因此在操作数据之前就先加锁,在整个操作过程中持有锁,阻止其他线程同时修改,直到操作完成才释放锁。

核心思想:"先锁住再干活";操作系统互斥锁,涉及内核态切换。

比喻:你进公厕,先把门锁上。外面的人看到门锁着,就知道里面有人,只能排队等。等完事了打开锁,下一个人才能进去。

特点:

  1. 锁竞争时线程阻塞排队,上下文切换、线程挂起唤醒有开销;
  2. 多锁嵌套时存在死锁风险;
  3. 一旦拿到锁,可连续多次修改,重试成本低。

Java 实现:

  • synchronized 关键字
  • ReentrantLock
  • 数据库的 SELECT ... FOR UPDATE

# 二、乐观锁(Optimistic Lock)

定义:乐观锁认为并发冲突很少发生,因此操作时不加锁,只在最后提交更新时检查一下,在这期间有没有其他人改过数据。如果有冲突,就放弃或重试。

核心思想:"先干活,提交时再检查有没有冲突";**CAS (Compare And Swap) ** 或版本号机制。

比喻:你用共享单车扫码骑走,没人拦你。但你锁车还车时,系统会检查这段时间有没有人同时扫了这辆车,有冲突就让你重试一下。

特点:

  1. 全程无线程阻塞,线程一直在运行;
  2. 无独占锁,天然不会产生死锁;
  3. 校验失败就重试,高冲突下会无限自旋。

Java 实现:

  • AtomicInteger(CAS 机制)

  • StampedLock

  • 数据库的 version 字段

    // 乐观锁示例(数据库 version 字段)
    UPDATE account 
    SET balance = balance - 100, version = version + 1
    WHERE id = 1 AND version = 5;  -- 期望版本还是 5
    -- 如果影响行数 = 0,说明被别人改过了,重试或放弃
    

# CAS 算乐观锁还是悲观锁?

CAS(Compare And Swap)是 CPU 硬件层面的原子操作,通常被认为是乐观锁的实现基础。

但严格来说,CAS 本身是无锁的,既不是乐观也不是悲观。它是乐观锁的"兵器",不是"兵法"。

// 伪代码 CAS 自增
while (!compareAndSwap(oldVal, oldVal + 1)) {
    // 重试,空循环
}

# AQS

AQS 本身不是锁,它既可以用来实现悲观锁(如 ReentrantLock),也可以用来实现乐观锁(如 CountDownLatch 的部分逻辑)

AQS (AbstractQueuedSynchronizer)是 Java 提供的一个用来构建锁和同步器的抽象框架。它维护了一个 volatile int state 状态变量 + 一个 FIFO 线程等待队列。

CAS 是硬件指令,AQS 是 Java 框架

阅读全文
×

(为防止恶意爬虫)
扫码或搜索:HelloCoder
发送:290992
即可永久解锁本站全部文章

解锁
#悲观锁#乐观锁
上次更新: 2026-06-08 17:48:15
最近更新
01
MySQL支持的锁有哪些
06-08
02
HTTP 是不保存状态的协议, 如何保存用户状态
06-08
03
WebSocket、短轮询、长轮询的区别
06-08
更多文章>
Theme by Vdoing | Copyright © 2020-2026 HaC
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式