概述
这个类是抽象类,一些方法需要子类来进行实现。
java.util.concurrent.locks.AbstractQueuedSynchronizer#tryAcquire
java.util.concurrent.locks.AbstractQueuedSynchronizer#tryRelease
java.util.concurrent.locks.AbstractQueuedSynchronizer#tryAcquireShared
java.util.concurrent.locks.AbstractQueuedSynchronizer#tryReleaseShared
java.util.concurrent.locks.AbstractQueuedSynchronizer#isHeldExclusively
核心的方法是aquire。此方法是独占模式下线程获取共享资源的顶层入口。如果获取到资源,线程直接返回,否则进入等待队列,直到获取到资源为止。
代码分析
AbstractQueuedSynchronizer在JUC的locks包中。
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
//空的
protected AbstractQueuedSynchronizer() { }
我们首先来看node对象
可以看到node其实就是连标上的一个节点。而且存储了这个节点对应的线程。我们可以通过这个线程的应用使用sun.misc.Unsafe#unpark对其进行unpark。
节点大致有如下状态
-
CANCELLED(1):表示当前结点已取消调度。当timeout或被中断(响应中断的情况下),会触发变更为此状态,进入该状态后的结点将不会再变化。
-
SIGNAL(-1):表示后继结点在等待当前结点唤醒。后继结点入队时,会将前继结点的状态更新为SIGNAL。
_ CONDITION(-2):表示结点等待在Condition上,当其他线程调用了Condition的signal()方法后,CONDITION状态的结点将从等待队列转移到同步队列中,等待获取同步锁。
- PROPAGATE(-3):共享模式下,前继结点不仅会唤醒其后继结点,同时也可能会唤醒后继的后继结点。
0:新结点入队时的默认状态。
内部存储着等待队列的头尾
/**
* Head of the wait queue, lazily initialized. Except for
* initialization, it is modified only via method setHead. Note:
* If head exists, its waitStatus is guaranteed not to be
* CANCELLED.
*/
private transient volatile Node head;
/**
* Tail of the wait queue, lazily initialized. Modified only via
* method enq to add new wait node.
*/
private transient volatile Node tail;
acquire()操作流程
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
//先加入队列,然后进行阻断
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
//阻断被唤醒后首先响应这段时间收到的中断
selfInterrupt();
}
- tryAcquire()尝试直接去获取资源,如果成功则直接返回(这里体现了非公平锁,每个线程获取锁时会尝试直接抢占加塞一次,而CLH队列中可能还有别的线程在等待);
- addWaiter()将该线程加入等待队列的尾部,并标记为独占模式;
- acquireQueued()使线程阻塞在等待队列中获取资源,一直获取到资源后才返回。如果在整个等待过程中被中断过,则返回true,否则返回false。
- 如果线程在等待过程中被中断过,它是不响应的。只是获取资源后才再进行自我中断selfInterrupt(),将中断补上。
注意,这里要传入一个整数值,用于子类实现者在实现tryAquire中使用。这里没有明确含义。
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
//shouldParkAfterFailedAcquire将检查或将前序节点设置为signal状态
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
//线程在被park时不会响应中断。在唤醒后将返回其中断状态
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
release操作流程
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
private void unparkSuccessor(Node node) {
/*
* If status is negative (i.e., possibly needing signal) try
* to clear in anticipation of signalling. It is OK if this
* fails or if status is changed by waiting thread.
*/
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
if (s != null)
LockSupport.unpark(s.thread);
}
ConditionObject
这个内部类不一定会在核心链路上使用的。
private transient Node firstWaiter;
/** Last node of condition queue. */
private transient Node lastWaiter;
作为自身内部链表【被称为等待队列】首尾节点。
一个AQS对象内部可能有多个condition对象,对应多个等待队列。
调用condition的signal方法时,将会把等待队列的首节点移到等待队列的尾部,然后唤醒该节点。
被唤醒,并不代表就会从await方法返回,也不代表该节点的线程能获取到锁,它一样需要加入到锁的竞争acquireQueued方法中去,只有成功竞争到锁,才能从await方法返回
public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignal(first);
}
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null)
lastWaiter = null;
first.nextWaiter = null;
} while (!transferForSignal(first) &&
(first = firstWaiter) != null);
}
/**
* Transfers a node from a condition queue onto sync queue.
* Returns true if successful.
* @param node the node
* @return true if successfully transferred (else the node was
* cancelled before signal)
*/
final boolean transferForSignal(Node node) {
/*
* If cannot change waitStatus, the node has been cancelled.
*/
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
return false;
/*
* Splice onto queue and try to set waitStatus of predecessor to
* indicate that thread is (probably) waiting. If cancelled or
* attempt to set waitStatus fails, wake up to resync (in which
* case the waitStatus can be transiently and harmlessly wrong).
*/
//将节点放到等待队列的结尾,并返回前序节点
Node p = enq(node);
int ws = p.waitStatus;
//ws>0表示取消调度,确认没有取消调度
//将前序节点状态设置为signal状态
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
//让这个线程继续运行
LockSupport.unpark(node.thread);
return true;
}
上面的signal上线程继续执行。那么线程究竟被wait在哪里的了呢?我们还是需要看wait的实现
调用condition的await方法,将会使当前线程进入等待队列并释放锁(先加入等待队列再释放锁),同时线程状态转为等待状态。
从同步队列和阻塞队列的角度看,调用await方法时,相当于同步队列的首节点移到condition的等待队列中
/**
* Implements interruptible condition wait.
* <ol>
* <li> If current thread is interrupted, throw InterruptedException.
* <li> Save lock state returned by {@link #getState}.
* <li> Invoke {@link #release} with saved state as argument,
* throwing IllegalMonitorStateException if it fails.
* <li> Block until signalled or interrupted.
* <li> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
* <li> If interrupted while blocked in step 4, throw InterruptedException.
* </ol>
*/
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//将该线程加到condition等待队列的队尾
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
可见,线程被唤醒后一样会进入到acquireQueued的逻辑去争取同步队列的锁。
再看ReentrantLock
无论是
ReentrantLock中的公平锁代码
final void lock() {
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();//等于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;
}
我们再来看看非公平锁的代码
final void lock() {
//如果没有则直接抢占
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
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;
}