可重入锁是一种多线程同步机制,允许同一线程多次获取同一个锁而不会导致死锁。这意味着一个线程可以在持有锁的情况下再次请求并获得相同的锁,而不会被自己阻塞。可重入锁有助于避免死锁和提高代码的可维护性,因为它允许在一个线程中嵌套地调用锁定的方法。
如我们常用的synchronized和reentrantLock都是比较典型的可重入锁。也就是说,在一个线程调用synchronized方法的同时,可以在其方法体内部调用该对象另一个synchronized方法,也就是说一个线程得到一个对象锁后再次请求该对象锁。
public class ReentrantLockTest {
public static void main(String[] args) {
ReentrantLockTest reentrantLockTest = new ReentrantLockTest();
reentrantLockTest.method1();
}
public synchronized void method1(){
method2();
System.out.println("invoke method1");
}
public synchronized void method2() {
System.out.println("invoke method2");
}
}
如以上代码,即可输出:
invoke method2
invoke method1
在可重入锁的实现上,一般是先要记录下来当前锁是归属于哪个线程的,然后再记录当前锁被重入了多少次。这样在加锁的时候判断是不是当前线程持有的锁,如果是则重入次数+1,否则重入失败。
在解锁时也同理,锁是当前线程加的,那就重入次数-1,直到等于0的时候,直接解锁。
以下就是reentrantLock的加锁代码:
if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
以下就是reentrantLock的解锁代码:
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}