1. 悲观锁 vs 乐观锁(心态问题)

  • 悲观锁:觉得肯定有人抢厕所,进去就反锁门(加锁),用完再开。
    → Java里的 synchronizedReentrantLock 都是这种。安全,但慢

  • 乐观锁:觉得没人抢,不锁门,但上厕所时盯着门把手(版本号/时间戳),如果发现被人动过(冲突),就重试。
    → Java里的 CAS(比较并交换) 就是这种,比如 AtomicInteger快,但冲突多时会反复重试


2. 公平锁 vs 非公平锁(排队问题)

  • 公平锁:先来后到,乖乖排队。
    new ReentrantLock(true)公平,但效率低(大家都得排队)。

  • 非公平锁:新来的可以插队,如果锁刚好释放,它就直接抢。
    synchronized 和默认的 ReentrantLock 都是非公平。效率高,但可能导致某些线程饿死(一直抢不到)。


3. 可重入锁(同一个人的多次进入)

  • 你进了厕所A,发现里面还有个小隔间B,你能直接进B,不用再掏钥匙。
    synchronizedReentrantLock 都支持。同一个线程可以多次获取同一把锁,防止自己把自己卡死。

4. 读写锁(分情况管理)

  • 厕所分蹲位(写锁)洗手池(读锁)
    • 多人同时洗手(读)没问题。
    • 但有人蹲坑(写)时,别人既不能蹲也不能洗手(全阻塞)。
      ReentrantReadWriteLock适合读多写少的场景。

5. 共享锁 vs 排他锁(权限级别)

  • 排他锁(写锁):厕所门一锁,谁也别进。
  • 共享锁(读锁):可以多人同时看同一份文件(但不能改)。
    → 读写锁就是共享/排他的典型实现。

6. 偏向锁 → 轻量级锁 → 重量级锁(锁升级,JVM自动优化)

这是 synchronized 的底层升级过程(为了性能):

  • 偏向锁:厕所只认你一个人,你每次来都不用掏钥匙(无竞争)。
  • 轻量级锁:偶尔有别人来,你们用“自旋”方式(原地转圈等)抢,不挂起线程(省资源)。
  • 重量级锁:竞争激烈,排队挂起(操作系统介入,慢)。
    → 这是JVM自动做的,你不用管,但知道它存在即可。

7. 自旋锁(不睡觉,死等)

  • 厕所被占,你不去排队睡觉,而是在门口原地转圈(循环检查),等它释放。
    → 适合持有锁时间很短的情况,避免线程挂起/唤醒的开销。Java里的 CAS 就是自旋思想。

8. 分段锁(分块管理)

  • 一个大厕所分成多个小隔间,锁只锁其中一间,不影响其他间。
    ConcurrentHashMap 早期就是用分段锁,提升并发度(现在改用CAS+细粒度锁了)。

一张图总结(按使用场景选):

场景 推荐锁
简单同步,代码少 synchronized
需要可中断、超时、公平等灵活功能 ReentrantLock
读多写少(如缓存) ReentrantReadWriteLock
计数器、自增等简单操作 AtomicXXX(乐观锁)
追求极致性能,竞争不激烈 偏向锁/轻量级锁(JVM自动)