前面介绍的是排他申请锁的情况,也就是synchronized语法支持的内容。但是业务中会有更加复杂的场景,通过对tryAcquire、tryRelease的覆写以及state属性的使用,我们可以达到控制并发的目的,满足具体的场景需求。但是许多场景都是有共性的,并且直接使用这些底层的方法去实现并发,一来代码复杂,二来容易出错,所以有必要针对这些场景封装出通用的并发组件,比如ReetrantLock。
AbstractQueuedSynchronizer是一个抽象类,要具体使用需要对它进行继承,一般的实现比如ReentrantLock都是以内部类的形式实现一个AbstractQueuedSynchronizer子类,在外边做相应封装。
ReentrantLock中对acquire和release的实现如下:
/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {//如果锁尚未被占用
if (compareAndSetState(0, acquires)) {//cas获得锁
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) {
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;
}
非公平锁的实现:
/**
* Sync object for non-fair locks
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1))//直接去抢占,而没有去管是否前面有等待的节点
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
公平锁的实现与非公平锁相差很小:
/**
* Sync object for fair locks
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
//多了一层前面没有等待的节点的判断
// 如果有等待中的节点,并且本节点非head的下一个节点,则不会去抢占锁
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;
}
}