ReentrantLock有以下几个特性。
基本的获取锁操作,基本的释放锁操作,可轮询的锁获取操作,可中断的获取锁操作,定时获取锁操作,使用公平队列。
首先ReentrantLock的实现主要是依赖于
AbstractQueuedSynchronizer。AbstractQueuedSynchronizer它维护一个状态信息单一的整数
state。state在此用来表示拥有锁的线程请求获取锁的次数。
state==0表示锁为可获取状态。
基本的获取锁操作:lock()方法:
public void lock() {
sync.lock();
}
sync为ReentrantLock静态内部类Sync的一个引用。
无参数的构造函数默认sync指向一个NonfairSync().(不公平队列)。Sync扩展了AbstractQueuedSynchronizer.而NonfairSync扩展了Sync.
NonfairSync中lock()方法的实现如下:
final void lock() {
if (compareAndSetState(0, 1))//AbstractQueuedSynchronizer的方法(原子操作),如果当前的state的值为0则把state的值设为1
setExclusiveOwnerThread(Thread.currentThread());//设置当前锁的有占有者为当前线程
else
acquire(1);//如果是拥有锁的线程请求state++,否则当前线程阻塞,并且把线程存储到阻塞队列中。(AbstractQueuedSynchronizer中使用链表来维护的线程阻塞队列)
}
可轮询的锁获取操作:具体的实现为:
final boolean nonfairTryAcquire(int acquires) {//此处acquirs为1
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {//如果state为0证明锁可获取
if (compareAndSetState(0, acquires)) {//原子操作,如果当前的state为0,则把state的值设置为1.
setExclusiveOwnerThread(current);//设置当前锁的占有者为当前线程
return true;
}
}
else if (current == getExclusiveOwnerThread()) {//如果当前锁的占有者为当前线程
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);//设置state为占有锁线程请求锁的次数
return true;
}
return false;
}
基本的释放锁操作:
protected final boolean tryRelease(int releases) {//此处releases值为1
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;
}
使用公平队列:公平队列的获取锁操作和非公平队列获取锁操作的主要区别在于多了一个判断isFirst(current)判断当前的线程是否是阻塞队列中第一个元素。以此来实现公平队列。
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (isFirst(current) && //与非公平队列的主要不同点
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
ReentrantLock的实现主要依赖于AbstractQueueSynchronizer,但是ReentrantLock不是扩展AQS而是使用委托,使用静态内部类。这样有个好处在于保持类的整洁性,只暴露需要对外公开的方法。如果扩展AQS的话就会暴露过多的方法,调用者容易误调用这些方法。