一、简介
众所周知,Java并发组件中的一个重要框架就是AQS,简称同步器。全称AbstractQueuedSynchronizer,它是基于模板方法模式实现的。也就是说大体算法框架已经写好了,具体的一些细节需要用户去实现。AQS中有5个方法是用户根据需要实现的(排它锁与否):
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
protected boolean isHeldExclusively() {
throw new UnsupportedOperationException();
}
二、ReentrantLock的骨架
ReentrantLock是排它锁,需要实现上面的两个排它方式的方法。看一下ReentrantLock的内部构造:
ReentrantLock锁依赖于Sync:
public class ReentrantLock implements Lock {
...
private final Sync sync;
...
}
并在内部实现了Sync:
abstract static class Sync extends AbstractQueuedSynchronizer {
abstract void lock();
final boolean nonfairTryAcquire(int acquires) {
...
}
protected final boolean tryRelease(int releases){...}
protected final boolean isHeldExclusively() {...}
...
}
分析:
ReentrantLock 是独占锁,所以说需要实现抽象类 AbstractQueuedSynchronizer 中的两个方法: tryRelease(int releases)
和tryAcquire(int acquires)
。
从上面可以看出,它只实现了其中一个 tryRelease
,其实 tryAcquire
是在子类中实现了。Sync有两个子类,分别是:
static final class NonfairSync extends Sync {...}
static final class FairSync extends Sync {...}
即非公平锁和公平锁的组件。
1、非公平锁:
static final class NonfairSync extends Sync {
/**
* 1)首先基于CAS将state(锁数量)从0设置为1,如果设置成功,设置当前线程为独占锁的线程;-->请求成功-->第一次插队
* 2)如果设置失败(即当前的锁数量可能已经为1了,即在尝试的过程中,已经被其他线程先一步占有了锁),这个时候当前线程执行acquire(1)方法
*/
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
分析:
Sync实现了 tryRealease 方法。在子类 NonfairSync 中,实现了 tryAcquire
,它是以非公平的方式获取锁。上面的acquire()
函数在AQS中已经实现了,其中就调用了这里实现的tryAcquire()
方法。
2、公平锁:
static final class FairSync extends Sync {
final void lock() {
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//c为0的时候可以获取锁
if (c == 0) {
//当前节点没有前驱的时候才真正去获取锁
if (!hasQueuedPredecessors() &&
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;
}
}
分析:
在FairSync中,也同样实现了tryAcquire()
,它是以公平的方式获取锁。注意和 Sync 中的tryAcquire()
作比较。lock()
里面的acquire(1)
方法在AQS中已经实现了,其中就调用了这里实现的tryAcquire()
方法。
好了,至此上面所说的两个函数都实现了: tryRelease
,tryAcquire
。
三、具体实现
既然Sync组件已经写好了,那么ReentrantLock中的方法就可以使用它了。上面说到,ReentrantLock依赖组件Sync,即:
public class ReentrantLock implements Lock {
...
private final Sync sync;
...
}
下面看一下ReentrantLock的具体实现:
1、构造函数:有两个,默认是非公平的。
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
2、获得锁:
public void lock() {
sync.lock();
}
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
}
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
}
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
3、释放锁
public void unlock() {
sync.release(1);
}
4、条件变量
public Condition newCondition() {
return sync.newCondition();
}
5、锁相关的工具性质的方法
public int getHoldCount() {
return sync.getHoldCount();
}
public boolean isHeldByCurrentThread() {
return sync.isHeldExclusively();
}
public boolean isLocked() {
return sync.isLocked();
}
public final boolean isFair() {
return sync instanceof FairSync;
}
protected Thread getOwner() {
return sync.getOwner();
}
public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
public final boolean hasQueuedThread(Thread thread) {
return sync.isQueued(thread);
}
public final int getQueueLength() {
return sync.getQueueLength();
}
protected Collection<Thread> getQueuedThreads() {
return sync.getQueuedThreads();
}
6、条件变量相关工具类方法
public boolean hasWaiters(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
}
public int getWaitQueueLength(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
}
protected Collection<Thread> getWaitingThreads(Condition condition) {
if (condition == null)
throw new NullPointerException();
if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
throw new IllegalArgumentException("not owner");
return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
}
可以看到,ReentrantLock方法的实现全部是依靠Sync的方法。而Sync又是继承了AQS,下面是整个的一个类图。
这篇文章只是分析个大概,并没有去详细剖析,主要是为了了解ReentrantLock的大致结构,掌握大局。OK。就先到这吧。