最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Java 中的 ReentrantLock 锁释放顺序对任务调度的影响
时间:2026-07-09 10:11:12 编辑:袖梨 来源:一聚教程网
ReentrantLock的锁释放顺序不决定调度顺序,真正起作用的是锁的公平性:公平锁严格按等待队列FIFO唤醒;非公平锁允许新线程插队抢占,释放仅是竞争机会窗口。
ReentrantLock 的锁释放顺序本身不直接决定任务调度顺序,真正起作用的是锁的类型(公平 or 非公平)以及线程获取锁时的策略。释放锁只是触发“谁该下一个获得锁”的判断时机,而这个判断逻辑由锁实例的公平性决定,不是由释放动作的先后或顺序控制的。
公平锁:释放后严格按等待队列顺序唤醒
公平锁在调用 unlock() 时,会从 AQS 同步队列头部取出最早等待的线程(FIFO),并让它尝试获取锁。这意味着:
- 线程进入等待队列的顺序 = 将来被唤醒的顺序
- 即使某个线程刚释放锁,它也不能插队重新抢锁;必须排到队尾重新等待
- 不会出现“刚释放就立刻重入”这种低延迟抢占,所有新请求都老老实实排队
非公平锁:释放后允许新线程“插队”竞争
非公平锁的 unlock() 只是唤醒等待队列中的一个线程(通常是头节点),但与此同时,任何新调用 lock() 的线程都会直接尝试 CAS 抢占锁——不管队列里有没有人等着。所以:
- 刚释放锁的线程,如果马上再次调用 lock(),很可能抢成功(尤其在低竞争时)
- 等待队列里的线程可能被反复跳过,导致饥饿
- 实际调度顺序是“抢到算数”,和释放顺序无关,只和抢锁时机、CPU 调度、CAS 成功率有关
释放顺序 ≠ 执行顺序,更不等于调度优先级
多个线程依次调用 unlock(),并不会形成某种“释放队列”来影响后续调度。JVM 线程调度器不感知 unlock 调用顺序,AQS 也不记录“谁先释放”。关键区别只在两点:
立即学习“Java免费学习笔记(深入)”;
- 公平锁:唤醒固定为队首线程,释放动作只是触发点
- 非公平锁:唤醒 + 允许新线程无条件竞争,释放动作只是潜在机会窗口之一
实践中要注意的误区
有人误以为“先 unlock 的线程,后续就更容易拿到锁”,这是不成立的。例如:
- 线程 A 释放锁后立刻 sleep(1),线程 B 此时调用 lock(),大概率抢到——这不是因为 B “后释放”,而是因为它“先抢”
- 公平锁下,即使线程 C 比 D 早 1 微秒调用 unlock(),也不会让 C 在下次 lock() 中获得优先权;它仍要和其他等待者一起排队
- 锁释放后的调度结果,取决于当前是否有线程正在调用 lock(),以及锁的公平模式,而不是释放动作本身的顺序
不复杂但容易忽略:锁释放只是门开了,谁进门,得看门上贴的是“排队入场”还是“先到先撞门”。
相关文章
- 《Disney Lorcana: Wilds Unknown》预购开启 首批《Toy Story》及皮克斯卡牌购买指南 07-29
- 车来了赶车闹钟如何设置 07-29
- 崩坏星穹铁道余晖残卷巨剑守护打法攻略 07-29
- 崩坏星穹铁道砂金角色部分背景介绍 07-29
- 崩坏3雷电芽衣什么时候上线 07-29
- 玩具熊的五夜后宫4代噩梦气球男孩Nightmare Balloon Boy介绍 07-29