该文只是作为个人对于占小狼关于深入浅出java同步器AQS文的自己一些补充,建议先看他的文章之后再来看该文。有理解不对的地方望提出来共同学习。
AQS实现原理是通过子类重写tryAcquire和tryRelease方法通过CAS指令修改状态变量state。(接下来我们会将AbstractQueuedSynchronizer简写成AQS方便书写)
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
而我这里想解释下RreentrantLock内部对于tryAcquire()以及tryRelease()的一些自己理解。
对于RreentrantLock主要内部是通过构造的时候,判断内部使用公平锁还是非公平锁从而导致使用的时候有一些差异。
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
这里公平锁FairSync和NonfairSync都是继承自Sync,我们先看下Sync。
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
/**
* Performs {@link Lock#lock}. The main reason for subclassing
* is to allow fast path for nonfair version.
*/
//lock是由我们的子类来实现
abstract void lock();
/**
* Performs non-fair tryLock. tryAcquire is implemented in
* subclasses, but both need nonfair try for trylock method.
*/
//他默认实现了非公平锁的Acquire, 通过isLocked方法我们可以知道,state为0的时候为未上锁状态,而非0则为上锁状态
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
//如果没有上锁,直接通过CAS修改state,如果修改成功,则说明请求锁成功,将exclusiveOwnerThread设置为当前线程,这个属性实际是AQS父类AbstractOwnableSynchronizer内的属性,实际就是为了记录当前线程
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//这里如果已经上锁了,则判断当前上锁的线程是否为当前线程,是的话继续操作,否则直接返回false
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;
}
protected final boolean isHeldExclusively() {
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
return getExclusiveOwnerThread() == Thread.currentThread();
}
final ConditionObject newCondition() {
return new ConditionObject();
}
// Methods relayed from outer class
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
final boolean isLocked() {
return getState() != 0;
}
/**
* Reconstitutes the instance from a stream (that is, deserializes it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
接下来看下非公平锁:
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
//非公平锁会直接去设置state,如果当前state=0则直接相当于获得锁,否则就调用了AQS的acquire(1)
//我理解非公平锁不公平的原因在于比如现在AQS的等待队列有两个在等待获得锁的线程,当前获得锁的线程释放了锁,而这时候我们使用NonfairSync调用lock
//的时候,不需要看等待队列是否有等待获得锁的线程,而是直接和等待队列的下一个获得锁的线程竞争锁,如果竞争成功了,从而直接获得了该锁,导致
//等待队列中应该获得锁的线程继续等待,从而导致了不公平性。
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
接下来再看下公平锁:
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
//根据上面的分析,这里直接调用AQS的acquire,如果没有获得锁则直接加入到AQS的等待锁的线程队列,从而下次有锁释放直接从队列第一位获得锁,保证了公平性
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) {
//判断是否等待队列中还有在等待的线程,这个代码我单独拿出来说明下
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;
}
}
AQS的hasQueuedPredecessors:
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
//尾节点
Node t = tail; // Read fields in reverse initialization order
//头节点
Node h = head;
Node s;
//如果尾节点==头节点的时候,这个时候我们认为等待队列没有在等待的线程
//如果头节点!=尾节点但是头节点head.next == null,那么这种情况可能是这个时候正好被锁的线程释放锁,并且等待队列只有一个等待,直接变为了head从而head.next变为空,所以说明肯定是有前一个要获得锁或者等待锁的节点
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}