当前位置: 首页 > news >正文

ReentrantLock 公平锁 非公平锁底层实现原理

目录

一、基础铺垫:ReentrantLock 的核心结构

二、非公平锁(NonfairSync)底层实现

1. 加锁核心流程

2. 非公平锁关键特性

三、公平锁(FairSync)底层实现

1. 加锁核心流程

2. 公平锁关键特性

四、释放锁逻辑(公平 / 非公平完全一致)

五、核心区别总结(底层实现)

总结


ReentrantLock是 Java 中基于 AQS(AbstractQueuedSynchronizer,抽象队列同步器)实现的可重入锁,公平锁和非公平锁的核心区别:线程获取锁的顺序是否严格遵循等待队列的 FIFO(先进先出)规则

先明确核心结论:

  • 非公平锁:新线程来抢锁时,先直接尝试插队抢占锁,抢不到再进入等待队列排队;
  • 公平锁绝对禁止插队,新线程来抢锁时,先检查队列里有没有其他线程在等待,有就直接排队,不尝试抢占。

一、基础铺垫:ReentrantLock 的核心结构

  1. ReentrantLock内部定义了Sync抽象类(继承 AQS),公平锁FairSync、非公平锁NonfairSync都继承自 Sync;
  2. AQS 核心组件:
    • state:int 变量,0=无锁>0=持有锁(重入次数)
    • exclusiveOwnerThread:记录当前持有锁的线程;
    • CLH 等待队列:双向链表,存储抢不到锁的等待线程。
  3. 可重入特性:同一个线程多次获取锁时,state累加,释放锁时递减,直到state=0才真正释放锁。

二、非公平锁(NonfairSync)底层实现

核心设计:先插队,失败再排队,追求更高吞吐量(默认锁)。

1. 加锁核心流程

// 非公平锁lock()方法 final void lock() { // 第一步:直接插队!CAS尝试将state从0改为1(抢占锁) if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); // 抢占成功,设置持有线程 else acquire(1); // 抢占失败,走标准AQS获取锁逻辑 } // AQS的acquire方法(非公平/公平锁通用骨架) public final void acquire(int arg) { // 1. 再次尝试获取锁 2. 获取失败则入队等待 if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } // 非公平锁的tryAcquire(重写AQS方法) protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } // 非公平锁核心获取逻辑 final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { // 锁空闲 // 再次插队!CAS抢锁(不检查队列) if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } // 可重入:当前线程已持有锁,state+1 else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; setState(nextc); return true; } return false; // 抢锁失败 }

2. 非公平锁关键特性

  1. 两次插队机会
    • 第一次:lock()直接 CAS 抢锁;
    • 第二次:tryAcquire()发现锁空闲,再次 CAS 抢锁;
  2. 不检查等待队列:只要锁空闲,新线程可以直接抢走,不管队列里有没有等待很久的线程;
  3. 优点:减少线程上下文切换,吞吐量高;缺点:可能导致队列线程 "饥饿"(长时间抢不到锁)。

三、公平锁(FairSync)底层实现

核心设计:不插队,先检查队列,排队获取锁,保证严格的先来先服务。

1. 加锁核心流程

// 公平锁lock()方法(直接走acquire,没有插队CAS) final void lock() { acquire(1); } // 公平锁的tryAcquire(重写AQS方法) protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { // 核心区别:先检查队列!hasQueuedPredecessors()=队列有等待线程 if (!hasQueuedPredecessors() && // 队列空,才允许抢锁 compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } // 可重入逻辑和非公平锁完全一致 else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; setState(nextc); return true; } return false; }

2. 公平锁关键特性

  1. 禁止任何插队lock()直接走标准流程,没有 CAS 抢占
  2. 强制检查队列hasQueuedPredecessors()是核心判断:
    • 如果队列里有其他线程在等待 → 新线程直接入队,不抢锁;
    • 只有队列为空 / 自己是队首线程 → 才允许抢锁;
  3. 优点:无线程饥饿,严格公平;缺点:频繁上下文切换,吞吐量低于非公平锁。

四、释放锁逻辑(公平 / 非公平完全一致)

释放锁没有公平性区别,核心都是:

  1. state递减;
  2. state=0时,释放持有线程,唤醒队列中的下一个等待线程。
public void unlock() { sync.release(1); } public final boolean release(int arg) { if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); // 唤醒队列下一个线程 return true; } return false; } // 释放锁:state-1,为0时释放锁 protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; }

五、核心区别总结(底层实现)

对比维度非公平锁(NonfairSync)公平锁(FairSync)
抢锁入口lock()先 CAS 插队抢锁直接走acquire(),不插队
锁空闲时不检查队列,直接 CAS 抢锁必须先检查hasQueuedPredecessors()
等待队列新线程可能跳过队列严格遵守 FIFO 队列顺序
线程饥饿可能出现不会出现
吞吐量
底层差异无队列检查多了hasQueuedPredecessors()判断

总结

  1. 底层基石:公平 / 非公平锁都基于AQS实现,核心差异在tryAcquire()抢锁逻辑;
  2. 非公平锁插队优先,两次 CAS 抢锁,不检查等待队列,吞吐量更高;
  3. 公平锁排队优先,强制检查队列,绝对禁止插队,无饥饿但性能更低;
  4. 通用特性:可重入、锁释放逻辑、CLH 等待队列、AQS 的state状态管理完全一致。
http://www.jsqmd.com/news/897173/

相关文章:

  • qmc-decoder:专业级QQ音乐加密格式转换工具,3步解锁你的音乐收藏
  • 从理论到实践:使用sklearn解锁神经网络反向传播的鸢尾花分类实战
  • 锋芒剪辑-dota2自动剪辑微信小程序
  • JiYuTrainer技术实现:Windows系统级进程控制与反监控机制解析
  • 情境感知与自适应学习:UTROLL/KANTEAM移动语言学习系统架构解析
  • 重庆黄金回收为什么别选小店?对比宝奢、典表,合扬优势更明显 - 合扬奢侈品交易中心
  • 什么是阻抗匹配?功率传输和防止信号反射的理由及原理
  • 新手入门指南使用 Python 快速调用 Taotoken 提供的各类大模型
  • 古典乐理教师集体沉默的真相(内部培训PPT流出):ChatGPT已能完成本科《和声学II》全部作业,但仅7.3%用户掌握“约束型提问法”
  • 从99.77%到99.8%:PyTorch CNN在MNIST上的超参数调优与模型微调实战
  • 领航元启GEO品牌内容战略与AI营销服务 - 资讯焦点
  • 测试岗缩编30%后,活下来的人都悄悄搭了这套系统
  • 青岛企业发生股权纠纷不用慌!青岛资深股权律师李杰:专注解决各类公司股权争议 - 资讯纵览
  • 基于LPC-FCN的轻量级触觉纹理识别:边缘计算中的高效解决方案
  • 腾讯文档裁员风波:大厂“降本增效”背后的技术团队生存法则
  • 基于SDR的5G智能手机八天线MIMO实时测试平台构建与验证
  • 大模型边缘部署新突破:混合精度与对数量化实现4比特以下高效压缩
  • Boss-Key:Windows办公隐私保护终极指南,一键隐藏窗口告别尴尬时刻
  • 面霸AI:用Multi-Agent让面试模拟卷死同行
  • 基于BLS熵与t-SNE的形状聚类:从网络熵到无监督分类的实践
  • 如何在Windows 10上免费运行Android应用:专业级跨平台解决方案
  • 玉溪市红塔区黄金回收实战指南:991元/克大盘价下,这六家机构值得收藏 - 润富黄金珠宝行
  • 《大模型微调成本从 10 万降到 1000 元!LoRA+QLoRA 实战指南》
  • 从《Project Hail Mary》到星际导航:当科幻照进现实的技术图谱
  • 抛弃内存毒瘤IDEA,AI编码时代轻量编辑器zed开发调试java教程
  • 神经形态计算与人形机器人融合:基于STDP的脉冲神经网络实现视觉注意学习
  • 移动目标防御有效性评估:基于系统攻击面与隐马尔可夫模型的量化分析
  • 戴森球计划工厂蓝图仓库:8000+优化布局的终极模块化解决方案
  • 思源宋体TTF:跨平台中文字体配置与性能优化完全指南
  • 为什么这么多人会选择全日制MBA?就读全日制 MBA 能收获什么?