Java 并发锁核心分类与机制解析
在多线程开发中,锁是保障数据一致性的基石。理解不同锁的分类及其底层机制,能帮助我们根据场景选择更高效的同步方案。
公平锁与非公平锁
公平锁遵循先来后到的原则,多个线程按申请顺序获取锁;而非公平锁则允许插队,后申请的线程可能比先申请的优先获取。这种机制虽然可能导致饥饿现象或优先级反转,但通常吞吐量更高。
在 Java 中,ReentrantLock 支持通过构造函数指定是否公平,默认是非公平锁。Synchronized 关键字也是非公平的,且由于底层实现并未像 ReentrantLock 那样提供基于 AQS 的公平性配置接口,因此无法强制开启公平模式。
可重入锁
可重入锁(递归锁)允许同一个线程在外层方法持有锁时,再次进入内层方法自动获取锁,无需重复加锁。这有效避免了死锁问题。
ReentrantLock 和 Synchronized 都支持可重入特性。看个例子:
public class Demo {
public synchronized void setA() throws Exception {
Thread.sleep(1000);
setB(); // 当前线程再次获取锁,不会死锁
}
public synchronized void setB() throws Exception {
Thread.sleep(1000);
}
}
如果锁不可重入,setB 调用时会因等待自己持有的锁而陷入死循环。可重入机制让代码逻辑更清晰,减少了手动管理锁状态的复杂度。
独享锁与共享锁
- 独享锁:同一时刻只能被一个线程持有,如
ReentrantLock和Synchronized。 - 共享锁:可同时被多个线程持有,典型代表是
ReadWriteLock的读锁。
读写锁将锁细分为读锁和写锁。读锁允许多个线程并发读取,写锁则是独享的。这种设计在保证读写互斥的前提下,极大提升了读多写少场景下的并发效率。底层实现上,它们通常依赖 AQS 的不同状态位来区分独占与共享模式。
互斥锁与读写锁
从广义上讲,独享锁即互斥锁,共享锁对应读写锁中的读部分。具体到 Java API:
- 互斥锁:
ReentrantLock是最典型的实现。 - 读写锁:
ReentrantReadWriteLock提供了具体的读写分离控制。
乐观锁与悲观锁
这两者并非具体的锁类,而是看待并发冲突的哲学。
- :假设并发修改必然发生,操作前先加锁。Java 中的各种锁机制都属于此类,适合写操作频繁的场景。

