一、简介
众所周知,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) {
final Thread current = Thread.currentThread();
int c = getState();
//c = 0 的时候直接获取锁,非公平的,没有去查看队列前面
//还有没有其他线程在获得锁
if (c == 0) {
if (compareAndSetState(0, acquires)) {
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);
return true;
}
return false;
}
protected final boolean tryRelease(int releases){...}
protected final boolean isHeldExclusively() {...}
...
}
分析:
ReentrantLock 是独占锁,按理说需要实现抽象类 AbstractQueuedSynchronizer 中的以下两种方法: tryRelease 和tryAcquire。
从上面可以看出,它只实现了其中一个,接着往下看可以发现,tryAcquire(int arg) 在子类中实现了。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,如果设置成功,
* 设置当前线程为独占锁的线程;-->请求成功-->第一次插队
* 即在尝试的过程中,已经被其他线程先一步占有了锁),
* 这个时候当前线程执行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默认实现了非公平锁获取的方法。在NonfairSync中,实现了boolean tryAcquire(int acquires),即以非公平的方式获取锁。上面的acquire(1)函数在AQS中已经实现了,其中就调用了这里实现的boolean tryAcquire(int acquires)方法。
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中,实现了boolean tryAcquire(int acquires),即以公平的方式获取锁。注意和 Sync 中的 final boolean nonfairTryAcquire(int acquires) 作比较。Lock()里面的acquire(1)函数在AQS中已经实现了,其中就调用了这里实现的boolean tryAcquire(int acquires)方法。
好了,至此上面所说的两个函数都实现了: 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;
}
//返回持有该锁的线程,没有的话返回null
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,所以重点就是分析AQS。
这篇文章只是分析个大概,并没有去详细剖析,主要是为了了解ReentrantLock的大致结构,掌握大局。