职场里最让人崩溃的场景是什么?不是加班,而是早上抢厕所。
你想想:一间厕所,三个急得不行的同事,谁先上?怎么排队?万一有人锁门不出来?
今天咱们就把多线程并发和锁,聊成一场厕所争夺战。
1. 为什么需要锁?——因为资源有限
公司里只有一间厕所(共享资源),张三、李四、王五三个人(多个线程)都想用。
如果不加规则,三个人同时冲进去……那画面太美不敢看。
所以厕所门上的锁就派上了用场:谁抢到锁,谁进去,其他人乖乖排队。
对应到安卓里,多个线程同时操作同一个变量或文件,不加锁就会数据错乱——好比三个人同时记账,你写+1,他写-1,最后账对不上。
synchronized 就是公司统一装的自动感应门锁:你进去自动锁上,出来自动打开,不用操心。而且现在JVM和ART对它做了锁升级(平时很轻快,只有争抢激烈时才变重),性能并不差。
2. 锁的公平与非公平——排队能插队吗?
有的公司厕所门口自觉排队(公平锁),先来的人先进。
有的公司靠抢,谁跑得快谁先进(非公平锁)。非公平锁效率高,但可能导致有人等很久“饿死”。
Java 里的 ReentrantLock 让你自己选:new ReentrantLock(true) 公平排队,false(默认)非公平抢着进。
可重入锁又是什么?意思是:你已经占着厕所了,突然想起来忘了拿手机,还能再进去一次——同一个线程可以多次获得同一把锁,不会死锁。
⚠️ 但
ReentrantLock是密码锁,必须手动unlock()。如果你忘了在finally里关锁,异常时门就永远锁死。而synchronized自动门锁会在异常时自动释放,更安全。
3. 死锁——你等我,我等你,大家一起憋着
最恐怖的情况:
张三进了厕所A,手里还攥着厕所B的钥匙;李四进了厕所B,手里攥着厕所A的钥匙。
两人都在等对方出来,谁也不放手——这就是死锁。
怎么避免?按顺序拿钥匙:比如给厕所编号,只能按1→2的顺序申请。或者加超时:等太久就主动放弃,释放自己的锁。
4. 锁的粒度——别把整栋楼都锁了
有人上厕所,顺手把整层楼的厕所全锁上——这就是粗粒度锁,性能极差。
聪明的做法:只锁自己用的那间。
对应到代码,synchronized 可以锁整个方法(粗),也可以只锁几行核心代码(细)。锁的粒度越小,并发越高。
5. 厕所门口的“有人/无人”牌子——volatile的作用
有时候你并不需要锁门,只需要知道厕所是否被占用这个状态(一个boolean变量)。
如果A线程把牌子翻到“有人”,B线程却看不到(可见性问题),就会直接拉门闯进去。
这时用volatile修饰这个标志:保证一个线程改了,其他线程立刻能看见。它比锁轻量得多,专门解决可见性,不解决原子性。
6. 等待与唤醒——厕所里的“稍等”牌子
张三蹲在里面,突然发现没纸了,他不能直接出来,但也不想一直锁着门。
他可以wait:主动释放锁,在厕所里喊“我先让出来,你们谁帮我拿包纸,拿到再叫我”。
外面李四拿到纸后notify:“纸来了,你继续”。
这就是Object.wait/notify机制,用于线程间的协作,而不是单纯的互斥。
总结表格
| 概念 | 生活比喻 | 技术实现 |
|---|---|---|
| 共享资源 | 公司唯一的厕所 | 多线程访问的变量/文件 |
| 互斥机制(内置锁) | 自动感应门锁(synchronized) | JVM自动管理,异常释放 |
| 互斥机制(显式锁) | 密码锁(ReentrantLock) | 手动lock/unlock,需finally |
| 公平锁 | 排队上厕所 | 先到先得,开销大 |
| 非公平锁 | 冲进去抢 | 效率高,可能线程饿死 |
| 可重入锁 | 拿手机再进去 | 同一线程可多次获得锁 |
| 死锁 | 你等我、我等你 | 互相持有对方需要的锁 |
| 锁粒度 | 锁一间 vs 锁一层楼 | 细粒度提高并发 |
| 可见性 | 厕所门口的状态牌 | volatile(轻量通知) |
| 等待/通知 | 蹲坑喊人帮忙 | wait/notify(线程协作) |
面试官爱怎么问?
问:什么是死锁?怎么避免?
答:就像两个人互相等对方出厕所,结果谁都出不来。避免方法:按固定顺序拿锁,或者用tryLock(timeout)设置超时放弃。
问:synchronized 和 ReentrantLock 有什么区别?
答:synchronized是自动门锁(异常自动释放,JVM有锁升级优化);ReentrantLock是密码锁(功能多:公平、可中断、可超时),但必须手动在finally里解锁,否则会永久死锁。
问:volatile 能替代 synchronized 吗?
答:不能。volatile只保证你看到“有人/无人”的牌子(可见性),但不保证三个人同时翻牌子时的原子操作。好比牌子从“无人”变“有人”这个过程如果被两个线程同时做,还是会乱。
人话总结
并发就是多人抢资源,锁就是厕所门闩——没锁天下大乱,锁不好可能集体憋死。而volatile只是门口的提示牌,别拿它当锁用。
汇总导航