ReentrantLock - 可重入互斥锁

锁的可重入性

先举例来说明锁的可重入性:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class UnReentrant{
Lock lock = new Lock();
public void outer(){
lock.lock();
inner();
lock.unlock();
}
public void inner(){
lock.lock();
//do something
lock.unlock();
}
}

outer 中调用了 inner, outer 先锁住了 lock, 这样 inner 就不能再获取 lock。其实调用 outer 的线程已经获取了 lock 锁, 但是不能在 inner 中重复利用已经获取的锁资源, 这种锁即称之为 不可重入 。通常也称为 自旋锁 。相对来说, 可重入就意味着:线程可以进入任何一个它已经拥有的锁所同步着的代码块。

ReentrantLock 相比 synchronized 有如下几个优势

  1. 可以反复进入, 同一个线程获得几个锁, 在释放的时候也需要同等释放, 要不然会死锁的(其实 synchronized 也是可重入的);

  2. 支持锁中断 lockInterruptiblity(), 防死锁, 优先响应中断;

  3. 支持限时获取锁, lock.tryLock(int,TimeUnit); 在给定的时间范围捏尝试获取锁;

  4. 支持尝试获取锁, tryLock 不带参数, 如果获取不到则立刻返回 false, 而不等待锁;

  5. 公平锁 ReentrantLock(boolean fair), 排队获取锁, 性能相对低下;

  6. 配合 Condition, 可以让线程在合适的时间等待, 得到通知后继续执行。