一、什么是可重入性
可重入锁,就是同一个线程在外层方法获取锁之后,再次进入该锁的内层同步代码时,可以直接再次获取锁,不会被自己阻塞。
简单说:自己加的锁,自己可以重复进,不会死锁自己。
二、为什么说 synchronized 是可重入锁
因为 synchronized 底层是基于 Monitor 监视器 + 锁计数器 实现的:
线程第一次获取锁时,计数器置为 1
同一线程再次进入同步代码时,计数器 +1
每退出一层同步代码,计数器 -1
计数器为 0 时,才真正释放锁
所以同一个线程可以重复获取同一把锁,不会产生死锁,因此 synchronized 是可重入锁。
用代码举个例子就是:
public class Test {
public synchronized void a() {
b(); // 同一线程,再次进入 synchronized
}
public synchronized void b() {
// ...
}
}
调用 a() 时线程已经获取锁,再调用 b() 不会阻塞,这就是可重入。
顺便记一个加分点:
ReentrantLock 也是可重入锁,原理一样,靠 AQS 里的 state 计数器实现。
不可重入锁会导致:自己锁自己 → 死锁。
而对于这种不可重入锁最通用的解决办法就是使用可重入锁,通过记录锁持有线程和计数器,避免同一线程重复加锁时被阻塞。