什么是可重入锁
STFW得到以下两种主流解释
解释一:可重入就是说某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。
解释二:可重入锁又称递归锁,是指同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提是锁对象得是同一个对象),不会因为之前已经获取过锁还没有释放而阻塞。
疑惑
解释一中提到了可以再次获取锁,“再次获取锁”是如何进行判断的呢?
解释二中提到了可重入锁称为递归锁,因此就想当然的理解为可重入锁是某段代码方法中,一个锁里面嵌套着某个锁。那么难道锁不进行嵌套就不是可重入锁了吗?
解释一和解释二总感觉描述的不是一个东西。
证明
首先,我们已知ReentrantLock是可重入锁,那么它的可重入是怎么实现的呢,源码中有这样一段代码。
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
if (current == getExclusiveOwnerThread())这一段就是进行可重入锁的判断,因此可以得知,可重入锁就是在加锁时判断当前线程是否是已经获取到锁的线程,如果是的话,锁的次数会+1。需要注意的是既然多次加锁,就需要多次释放锁。
解释
解释一:可重入就是说某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。
这是可重入锁的概念描述。
解释二:可重入锁又称递归锁,是指同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提是锁对象得是同一个对象),不会因为之前已经获取过锁还没有释放而阻塞。
这是可重入锁的一种表现方式,不代表说某段代码中的锁没有发生嵌套,这个锁就不是可重入锁。
总结
可重入锁是某个线程已经获得某个锁,可以再次获取锁而不会出现死锁。再次获取锁的时候会判断当前线程是否是已经加锁的线程,如果是对锁的次数+1,释放锁的时候加了几次锁,就需要释放几次锁。
代码中的锁的递归只是锁的一种表现及证明形式,除了这种形式外,还有另一种表现形式。同一个线程在没有释放锁的情况下多次调用一个加锁方法,如果成功,则也说明是可重入锁。