Java语言提供了synchronized关键字用于加锁,但这种锁一是很重,二是获取时必须一直等待,没有额外的尝试机制。
从Java 5开始,引入了一个处理并发的java.util.concurrent
包,它提供了大量更高级的并发功能。其中Lock
是juc
包下面的一个接口,ReentrantLock
是它的常用实现类。
ReentrantLock
是一个可重入的,API层面上的互斥锁,用于替代synchronized
加锁。它拥有与synchronized
相同的并发性和内存语义,但是添加了定时锁等候、可中断锁等候等一些特性。
基本使用
传统synchronized
代码:
public class Counter {
private int count;
public void add(int n) {
synchronized(this) {
count += n;
}
}
}
复制代码
如果用ReentrantLock
替代,代码为:
public class Counter {
private final Lock lock = new ReentrantLock();
private int count;
public void add(int n) {
lock.lock();
try {
// synchronized do something
count += n;
} finally {
lock.unlock();
}
}
}
复制代码
synchronized
是 Java 语言层面提供的一个关键字,锁和获取和释放都不需要显式调用,在异常时也会自动释放锁。
与之相比,ReentrantLock
是 Java 语法层面提供的API,是一种手动锁,需要手动获取锁lock()
和释放锁unlock()
,并要手动处理异常。一方面使用更加灵活,另一方面也需要特别注意,一定要记得释放锁,不然就会造成死锁。
ReentrantLock
因为要手动释放锁,为避免异常时无法释放锁,需要配合try/finally
语句块来完成,在finally
中释放