发布于2026-07-08 阅读(0)
扫一扫,手机访问
说说 synchronized 的非公平性这事儿。很多人容易把锅甩给 wait/notify,其实根子不在这——真正的关键,是锁释放之后,JVM 到底按什么规则从 EntryList 里挑线程去唤醒。结论先放在这里:它不按先来后到,而是随机选。换句话说,你排了半天队,可能还不如一个新来的“插队”快。
当一个线程试图进入 synchronized 块,但锁已经被别人占着,它不会去哪儿排个号,而是被塞进一个单向链表结构——也就是 EntryList。这个结构本身不记录线程进入的时间,也不具备任何排序能力。
几个关键点值得记住:
说白了,这就像一个没人维持秩序的候车厅,门一开谁挤得快谁先上。
调用 wait() 的线程会主动退出临界区、释放锁,然后一头扎进 WaitSet。等到被 notify()
这就造成了一个双重的非确定性:一方面,WaitSet 里哪个线程先被唤醒本身就不确定;另一方面,被唤醒后挤进 EntryList,能不能赢下锁又是另一回事。两重不确定性叠加,公平性基本无从谈起。
跟 ReentrantLock(true) 显式开启的公平模式不同,synchronized 的底层 Monitor 实现——也就是 ObjectMonitor——在 JVM 源码里根本就没设计公平调度的路径。
ObjectMonitor::exit() 里,调用的是平台相关的线程调度接口,而不是从队列里依次取元素所以这不是 bug,是设计选择,而且是一个很务实的选择。
非公平不代表“错误”。只要程序满足了互斥、可见性和有序性这三个基本语义,逻辑上就是安全的。问题在于,你不能依赖线程的等待顺序来做任何时序上的假设。
ReentrantLock(true) 加 Condition 组合拳
总之,synchronized 的非公平性不是个“缺陷”,而是 JVM 工程师出于性能考量做的一个清醒取舍。理解了这个机制,你就能在并发编程中更清楚地判断:什么时候该用它,什么时候该换工具。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8