艰难攀爬游戏免安装绿色中文版
572M · 2025-09-28
原文来自于:zha-ge.cn/java/72
有时候写代码,感觉就像是在玩“谁先抢到麦克风谁发言”的游戏。偏偏,Java里的锁也差不多这个玩法——尤其是公平锁和非公平锁,简直是线程界的“内卷现场”。上次因为这俩差异差点背锅,今天就来和大家聊一聊这个血泪攒成的小故事。
那个需求很简单。老板说:“来个并发计数器,多线程下别出错就行。”
我美滋滋抄起 ReentrantLock
,心想Java库谁不会!查文档、复制粘贴,生产力爆棚。
最开始我用的就是:
ReentrantLock lock = new ReentrantLock(); // 默认非公平
实测QPS还挺高,多个线程打成一团,听起来气氛很好嘛(其实是互相抢麦)。
直到有一天,测试小哥扔来一句:“为啥有时候队首排很久都还没抢到资源?”我这才意识到——我这锁可是非公平的!线程A明明排头,却可能让后来者插队。
说实话,那一刻我差点怀疑人生。
我本以为锁很公平,大家排排队都会轮到自己。结果仔细一看:
受不了,赶紧贴个公平锁,然后是这样的:
ReentrantLock fairLock = new ReentrantLock(true); // true表示公平锁
我得意洋洋,想这下一定万无一失。
谁想新坑又来了——性能肉眼可见地下滑。原本20ms的操作,挂上公平锁就变成50ms了。摸了摸头发,难怪有些大厂文档说:“能不用公平锁就别用”。
突然想到之前面试官的阴笑:“你知道公平锁和非公平锁实际差异吗?”原来我之前全是在纸面谈兵。
说白了,公平 vs 非公平,主要有这些差距:
简单讲,非公平锁像春运抢票,拼手速。公平锁像有序取号排队,慢但有保障。
还抓了一段Lock源码瞅瞅:
if (fair) {
// 公平锁,调用tryAcquireFair,严格依赖队列
} else {
// 非公平锁,调用tryAcquire,直接抢
}
先对源码膜拜三秒,简直套路满满。
翻了这个小车以后,我总结了如下几点:
写Java多了我发现,锁其实就像小区门禁。 有的门“刷脸先到先进”,有的门“大爷插队我也能进”。 什么场景用什么门,自己权衡,别迷信公平,别嫌弃非公平。
最后,别像我一样踩坑才长记性,锁这东西,还是用脑借用同行的哭墙! 各位,别让锁玩了你,咱们要玩转锁!
—— 一个被锁支配过、但还愿意分享故事的Java程序员
572M · 2025-09-28
57.7G · 2025-09-28
3.61G · 2025-09-28