原来公平锁和非公平锁差别这么大

原文来自于:zha-ge.cn/java/72

原来公平锁和非公平锁差别这么大

有时候写代码,感觉就像是在玩"谁先抢到麦克风谁发言"的游戏。偏偏,Java里的锁也差不多这个玩法------尤其是公平锁和非公平锁,简直是线程界的"内卷现场"。上次因为这俩差异差点背锅,今天就来和大家聊一聊这个血泪攒成的小故事。

刚开始,怎么没毛病?

那个需求很简单。老板说:"来个并发计数器,多线程下别出错就行。" 我美滋滋抄起 ReentrantLock,心想Java库谁不会!查文档、复制粘贴,生产力爆棚。

最开始我用的就是:

java 复制代码
ReentrantLock lock = new ReentrantLock(); // 默认非公平

实测QPS还挺高,多个线程打成一团,听起来气氛很好嘛(其实是互相抢麦)。

直到有一天,测试小哥扔来一句:"为啥有时候队首排很久都还没抢到资源?"我这才意识到------我这锁可是非公平的!线程A明明排头,却可能让后来者插队。

踩坑瞬间

说实话,那一刻我差点怀疑人生。

我本以为锁很公平,大家排排队都会轮到自己。结果仔细一看:

  • 非公平锁(默认模式):新来的线程完全可以加塞!
  • 公平锁:讲究,永远遵守"谁先来,谁先服务"。

受不了,赶紧贴个公平锁,然后是这样的:

java 复制代码
ReentrantLock fairLock = new ReentrantLock(true); // true表示公平锁

我得意洋洋,想这下一定万无一失。

谁想新坑又来了------性能肉眼可见地下滑。原本20ms的操作,挂上公平锁就变成50ms了。摸了摸头发,难怪有些大厂文档说:"能不用公平锁就别用"。

突然想到之前面试官的阴笑:"你知道公平锁和非公平锁实际差异吗?"原来我之前全是在纸面谈兵。

真实区别:别光看表面

说白了,公平 vs 非公平,主要有这些差距:

  • 性能:
    • 非公平:速度快,因为直接抢,有点像抢红包,拼运气+手速。
    • 公平:大家排队,先来后到,但有调度成本,等得久。
  • 饥饿问题:
    • 非公平:某些倒霉蛋可能一直抢不到。
    • 公平:不会饿死谁,但可能整体效率低点。

简单讲,非公平锁像春运抢票,拼手速。公平锁像有序取号排队,慢但有保障。

还抓了一段Lock源码瞅瞅:

java 复制代码
if (fair) {
    // 公平锁,调用tryAcquireFair,严格依赖队列
} else {
    // 非公平锁,调用tryAcquire,直接抢
}

先对源码膜拜三秒,简直套路满满。

经验启示

翻了这个小车以后,我总结了如下几点:

  • 别滥用公平锁:不是"越公平越高级",性能真能打骨折。
  • 如果业务容忍偶尔不公平,选非公平锁,效率高,线程切换少。
  • 如果绝对不能让线程"饿死"(比如队首必须先服务),别犹豫上公平锁。
  • 读文档很重要:别光凭直觉用锁,不然坑自己都不知道。

别让锁玩了你

写Java多了我发现,锁其实就像小区门禁。 有的门"刷脸先到先进",有的门"大爷插队我也能进"。 什么场景用什么门,自己权衡,别迷信公平,别嫌弃非公平。

最后,别像我一样踩坑才长记性,锁这东西,还是用脑借用同行的哭墙! 各位,别让锁玩了你,咱们要玩转锁!

------ 一个被锁支配过、但还愿意分享故事的Java程序员

相关推荐
碧海蓝天202220 小时前
C++法则24:在标准 C++ 中,没有任何可移植的方式判断指针 T* pt 指向的内存位置是否已经 构造了对象,程序员必须手动跟踪哪些元素已构造。
java·开发语言·c++
один but you21 小时前
const和constexpr常量表达式
java·前端·javascript
码云数智-大飞21 小时前
RAII 与智能指针深度拆解
java·前端·算法
云烟成雨TD21 小时前
Agent Scope Java 2.x 系列【19】Harness:从零搭建 MySQL 文件系统
java·人工智能·agent
qq36219670521 小时前
阿里裁员新消息(2026最新动态汇总)
java·开发语言·前端
a11177621 小时前
“黑夜流星“个人引导页 网页html
java·前端·html
砚底藏山河21 小时前
沪深A股:如何获取基金持股数据
java·python·数据分析·maven
代码改善世界21 小时前
【C++进阶】C++11:列表初始化、右值引用与移动语义、完美转发全解析
java·开发语言·c++
AIGS00121 小时前
JBoltAI V4.5企业智能体平台:技术架构拆解
java·人工智能·ai大模型应用
一勺菠萝丶21 小时前
Maven SNAPSHOT 父 POM 无法解析问题排查
java·maven