Java 从 1.5 版本开始提供了 Lock 接口,主要是抽象锁相关的操作行为,其主要实现为 ReentrantLock
,也是最常用的锁的实现类,和 synchronized
一样,它也是可重入锁,而且还可以实现公平锁机制。
Lock 接口
Lock 接口位于 java.util.concurrent.locks 下,其接口定义如下:
public interface Lock {
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();
}
其中:
lock()
:获取锁的方法,它会阻塞程序,直到成功地获取锁。lockInterruptibly()
:与 lock() 不同的地方是,它可以响应程序中断,如果被其他程序中断了,则抛出InterruptedException
。tryLock()
:尝试获取锁,该方法会立即返回,并不会阻塞程序。如果获取锁成功,则返回 true,反之,则返回 false。tryLock(long time, TimeUnit unit)
:尝试获取锁,如果能获取锁,则直接返回 true;否则,阻塞等待,阻塞时长由传入的参数来决定,在等待时,如果发生了中断,则抛出 InterruptedException;如果在等待的时间中获取了锁,则返回 true,反之返回 false。unlock()
:释放锁的方法,通常放在 finally 代码块里。newCondition()
:新建一个条件,一个 Lock 可以关联多个条件。
ReentrantLock 使用
JDK 给出的示例如下:
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}
需要注意的是,加锁的过程 lock.lock();
放在了 try 的外部,这主要是如果放在 try 内部,如果获取锁操作失败,也都会执行释放锁操作(lock.unlock),但是由于当前线程加锁失败并没有持有 lock 对象锁,所以程序会抛出异常。