ReentrantLock重入锁

java.util.concurrent.locks包提供的ReentrantLock用于替代synchronized加锁

重入性

重入性指当线程需要再次获取同一把锁时, 不会因为自身而造成死锁, 锁的本质是作用于代码块或方法,而不是线程的整个执行上下文。即使线程已经持有锁,进入新的同步方法或代码块时,仍然需要执行获取锁的操作,确保锁的计数正确。

image.png

所以支持重入性应该解决下列问题

  • 由于获得多次相同的锁, 需要计数以释放相同次数
  • 相同线程再次获取锁应当直接成功, 防止死锁

为什么需要ReentrantLock

Java语言直接提供了synchronized关键字用于加锁,但这种锁一是很重,二是获取时必须一直等待,没有额外的尝试机制。

if (lock.tryLock(1, TimeUnit.SECONDS)) {
    try {
        ...
    } finally {
        lock.unlock();
    }
}

java.util.concurrent.locks包提供的ReentrantLock用于替代synchronized加锁

尝试获取锁的时候,最多等待1秒。如果1秒后仍未获取到锁,tryLock()返回false,程序就可以做一些额外处理,而不是无限等待下去。

所以,使用ReentrantLock比直接使用synchronized更安全,线程在tryLock()失败的时候不会导致死锁。

ReentrantLock使用

public class Counter {
	//和关键字不同, 需要获得一个重入锁对象
    private final Lock lock = new ReentrantLock();
    private int count;
	
    public void add(int n) {
		//代码块加锁
        lock.lock();
        try {
            count += n;
        } finally {
	        //在finally中解锁
            lock.unlock();
        }
    }
}