sync.lock();
}
// …
public void lockInterruptibly() throws InterruptedException {
sync.lockInterruptibly();
}
// 其它函数
复制代码
查看ReentrantLock源码可知,其内部有一个Sync类型的变量sync,上述代码列出了一些常见操作,均是调用sync里的对应方法。可见,ReetrantLock主要是通过sync这个变量来实现这些常见方法。
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
复制代码
接着查看Sync这个类,发现是ReetrantLock的内部类,继承了大名鼎鼎的AbstractQueuedSynchronizer(即AQS)类。跟锁有关的主要操作都是在这个类中实现。下面看一些具体的操作。
锁对象的创建
使用ReentrantLock,首先得用ReentrantLock lock = new ReentrantLock();
语句来创建一个锁的对象。看一下源码里ReentrantLock的构造函数。
public ReentrantLock() {
sync = new NonfairSync();
}
// other code
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
复制代码
可见,构造函数创建了Sync的对象sync(NonfairSync和FairSync都是Sync的子类,分别代表非公平锁和公平锁)。可以看出,默认的无参情况下,创建的是非公平锁;带参情况下,fair传true时,会创建公平锁。
获取锁
public void lock() {
sync.lock();
}
public boolean tryLock() {
return sync.tryLock();
}
复制代码
锁的获取主要是这两个函数,当然还有 lockInterruptibly( ) 和 tryLock(long timeout, TimeUnit unit) 这种响应中断和带时间限制的函数,不过和普通的lock( )和tryLock( )机理大致相同,就不介绍了。先以非公平锁的lock流程为例:
// 位于Sync中
final void lock() {
if (!initialTryLock())
acquire(1);
}
// 位于NonfairSync中
final boolean initialTryLock() {
Thread current = Thread.currentThread();
if (compareAndSetState(0, 1)) { // first attempt is unguarded
setExclusiveOwnerThread(current);
return true;
} else if (getExclusiveOwnerThread() == current) {
int c = getState() + 1;
if (c < 0) // overflow
throw new Error(“Maximum lock count exceeded”);
setState©;
return true;
} else
return false;
}
// 位于AQS中
public final void acquire(int arg) {
if (!tryAcquire(arg))
acquire(null, arg, false, false, false, 0L);
}
// 位于NonfairSync中的
protected final boolean tryAcquire(int acquires) {
if (getState() == 0 && compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
复制代码
可见,一个完整的最长的调用关系为:sync.lock( )->sync.initialTryLock( )->acquire(1)->tryAcquire(1)->acquire(many args)。
详细流程为:
先调用initialTryLock( ),方法首先尝试用CAS方式将state从0设置为1(state是AQS类的一个变量,用来说明锁是否被获取,自然被Sync类继承了),成功了就将此锁的拥有线程设置为此线程;否则,查看此线程是否已经拥有此锁,若是,则设置state的重入次数,由此可见,ReentrantLock是可重入锁,一个线程可多次获取。否则,返回false。
接着调用AQS类的acquire( ),首先会调用tryAcquire( )函数,这个函数是由NonfairSync重写的。在这里会再检查一下此锁是否被释放,若是,直接获取它,否则,返回false。
如果以上尝试都返回false了,说明这个锁一时半会确实获取不到,就调用AQS类的带许多参数的acquire( )函数,这个函数的作用是把这个线程放入这个锁的阻塞队列里。是AQS的内容,这里就不介绍了。
上面介绍了非公平锁的获取锁的流程。公平锁和非公平锁各自实现了initiTryLock( )和tryAcquire( )方法。对于公平锁来说,相较于非公平锁,获取锁的其它代码全都一样,只是在设置一个线程获取锁时,会多一个!hasQueuedThreads()
判断,这是AQS里的方法,作用是判断有没有线程在此线程前面被阻塞。这就体现了所谓的公平和非公平:非公平锁不检查有没有线程在它前面,只要发现锁可以获取就直接获取,所以不公平(你先等的,结果它时机凑巧,来的晚还把锁抢走了),公平锁就比较‘公平’了。
再看tryLock():
final boolean tryLock() {
Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(current);
return true;
}
} else if (getExclusiveOwnerThread() == current) {
if (++c < 0) // overflow
throw new Error(“Maximum lock count exceeded”);
setState©;
return true;
}
return false;
}
复制代码
这个方法在Sync类里实现,所以不管是不是公平锁,可以获取就直接获取锁。代码和initialTyeLock( )类似,就不解释了。同时也可以看出,tryLock( )并不会把线程加入到阻塞队列里,获取失败就直接返回false了。
锁的释放
位于Sync中
public void unlock() {
sync.release(1);
}
// 位于AQS中
public final boolean release(int arg) {
if (tryRelease(arg)) {
signalNext(head);
return true;
}
return false;
}
// 位于Sync中
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (getExclusiveOwnerThread() != Thread.currentThread())
throw new IllegalMonitorStateException();
boolean free = (c == 0);
if (free)
setExclusiveOwnerThread(null);
setState©;
return free;
}
复制代码
释放锁时,首先调用AQS中的release(1)函数,接着调用Sync重写的tryRelease( )函数,在这里将锁的重入数减一,如果state变为了0,说明此锁被释放了,进行释放锁的操作setExclusiveOwnerThread(null);
。如果锁被释放了,会接着调用AQS的signalNext( )函数功能。通知其它线程此锁可获得。
值得一提的是,这里的tryRelease( )函数和上述的tryAcquire( )函数不一样,后者由公平锁和非公平锁各自实现,而tryRelease( )则在Sync类里实现,公平锁和非公平锁共用。这是因为释放锁不用考虑是否公平,直接释放了就可以了。
创建条件对象
ReentrantLock另一个常用方法就是创建条件对象,在源码里也很简单。
public Condition newCondition() {
return sync.newCondition();
}
// 位于AQS
final ConditionObject newCondition() {
return new ConditionObject();
}
复制代码
newCondition( )方法和ConditionObject的主要操作都定义在AQS类里,这里不做介绍了。
一个ReentrantLock对象对应的阻塞和条件队列示意图如上。相关的AQS操作之后有空我会写一下。
锁的状态state
在上面获取和释放锁的代码里,经常会出现getState( )这个方法的身影。这个方法实际上是返回了state变量。state是AQS类的一个变量,在ReentrantLock里,用来标识锁的重入次数以及是否被持有。下面是关于它的一些方法:
private volatile int state;
protected final int getState() {
return state;
}
protected final void setState(int newState) {