方法名 | 作用 |
---|---|
boolean tryAcquire(int arg) | 尝试获取独占锁,没有成功则排队 |
boolean tryRelease(int arg) | 尝试释放独占锁 |
iint tryAcquireShared(int arg) | 尝试获取共享锁,没有成功则排队 |
boolean tryReleaseShared(int arg) | 尝试释放共享锁 |
boolean isHeldExclusively() | 判断当前线程是否独占锁 |
static final class Node {
static final Node SHARED = new Node();
static final Node EXCLUSIVE = null;
static final int CANCELLED = 1;
static final int SIGNAL = -1;
static final int CONDITION = -2;
static final int PROPAGATE = -3;
volatile int waitStatus;
volatile Node prev;
volatile Node next;
volatile Thread thread;
Node nextWaiter;
private static final VarHandle NEXT;
private static final VarHandle PREV;
private static final VarHandle THREAD;
private static final VarHandle WAITSTATUS;
}
public abstract class AbstractQueuedSynchronizer
extends AbstractOwnableSynchronizer
implements java.io.Serializable {
private transient volatile Node head;
private transient volatile Node tail;
private volatile int state;
private static final VarHandle STATE;
private static final VarHandle HEAD;
private static final VarHandle TAIL;
}
可以看出条件队列里面也是使用Node节点作为其组成,只是使用的是Node节点的nextWaiter属性,相当于单向链表
public class ConditionObject implements Condition, java.io.Serializable {
private transient Node firstWaiter;
private transient Node lastWaiter;
}
作用:获取队列中处于独占锁模式的线程列表
实现:从双向链表尾部开始查找,尾部查找原因在插入enq里面,如果Node节点不是共享节点,则取出节点中存放的线程并将其加入列表
public final Collection<Thread> getExclusiveQueuedThreads() {
ArrayList<Thread> list = new ArrayList<>();
for (Node p = tail; p != null; p = p.prev) {
if (!p.isShared()) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
}
return list;
}
作用:获取队列中第一个等待的线程
实现:如果头节点等于尾结点说明没有线程排队,否则执行fullGetFirstQueuedThread返回队头后面一个结点内部的线程,或者后续结点内部的线程
public final Thread getFirstQueuedThread() {
// handle only fast path, else relay
// 仅处理快速路径,否则为转发
return (head == tail) ? null : fullGetFirstQueuedThread();
}
private Thread fullGetFirstQueuedThread() {
Node h, s;
Thread st;
if ( //队头不为空 且 队头下一个也不为空 且队头的下一个的前一个为队头 且存储的线程也不为空
((h = head) != null && (s = h.next) != null &&
s.prev == head && (st = s.thread) != null)
||
//队头不为空 且 队头下一个也不为空 且队头的下一个的前一个为队头 且存储的线程也不为空
((h = head) != null && (s = h.next) != null &&
s.prev == head && (st = s.thread) != null)
)
return st;
Thread firstThread = null;
// 则从队列尾部开始往前找,找到最靠近队头的一个内部线程不为空的节点
for (Node p = tail; p != null && p != head; p = p.prev) {
Thread t = p.thread;
if (t != null)
firstThread = t;
}
return firstThread;
}
作用:获取队列中等待的线程集合
实现:从双向链表尾部开始查找,如果Node节点内部线程不为空,则取出节点中存放的线程并将其加入列表
public final Collection<Thread> getQueuedThreads() {
ArrayList<Thread> list = new ArrayList<>();
for (Node p = tail; p != null; p = p.prev) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
return list;
}
作用:获取队列中等待的线程数量
实现:从双向链表尾部开始查找,如果Node节点内部线程不为空,则计数器加1
public final int getQueueLength() {
int n = 0;
for (Node p = tail; p != null; p = p.prev) {
if (p.thread != null)
++n;
}
return n;
}
作用:获取队列中共享(共享锁)结点等待的线程集合
实现:从双向链表尾部开始查找,如果Node节点是共享结点且内部线程不为空,则取出节点中存放的线程并将其加入列表
public final Collection<Thread> getSharedQueuedThreads() {
ArrayList<Thread> list = new ArrayList<>();
for (Node p = tail; p != null; p = p.prev) {
if (p.isShared()) {
Thread t = p.thread;
if (t != null)
list.add(t);
}
}
return list;
}
作用:获取条件队列中等待的线程集合
实现:从单向链表中往后查询,找到Node状态为CONDITION且其内部线程不为null的结点,取出内部线程放入集合,同步队列和条件队列都使用Node结点作为其元素
public final Collection<Thread> getWaitingThreads(ConditionObject condition) {
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.getWaitingThreads();
}
从Node结点的nextWaiter单向链表实现的条件队列往后找,状态为CONDITION且内部线程Thread不为空的结点,取出其内部线程并放入集合
protected final Collection<Thread> getWaitingThreads() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
ArrayList<Thread> list = new ArrayList<>();
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION) {
Thread t = w.thread;
if (t != null)
list.add(t);
}
}
return list;
}
作用:获取条件队列中等待的线程数量
实现:从单向链表中往后查询,找到Node状态为CONDITION且其内部线程不为null的结点,计数器加1
public final int getWaitQueueLength(ConditionObject condition) {
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.getWaitQueueLength();
}
从Node结点的nextWaiter单向链表实现的条件队列往后找,如果结点状态为CONDITION则计数器加一
protected final int getWaitQueueLength() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
int n = 0;
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION)
++n;
}
return n;
}
作用:判断队列中有没有排队的线程
实现:
public final boolean hasQueuedPredecessors() {
Node h, s;
if ((h = head) != null) {
if ((s = h.next) == null || s.waitStatus > 0) {
s = null;
for (Node p = tail; p != h && p != null; p = p.prev) {
if (p.waitStatus <= 0)
s = p;
}
}
if (s != null && s.thread != Thread.currentThread())
return true;
}
return false;
}
作用:判断队列中有没有状态小于等于0的结点
public final boolean hasQueuedThreads() {
for (Node p = tail, h = head; p != h && p != null; p = p.prev)
if (p.waitStatus <= 0)
return true;
return false;
}
作用:判断队列中有没有排队的线程
实现:必须要获取错才能执行,判断条件队列中有无结点状态为CONDITION
public final boolean hasWaiters(ConditionObject condition) {
if (!owns(condition))
throw new IllegalArgumentException("Not owner");
return condition.hasWaiters();
}
protected final boolean hasWaiters() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
if (w.waitStatus == Node.CONDITION)
return true;
}
return false;
}
private Node enq(Node node) {
for (;;) {
// 获取尾节点
Node oldTail = tail;
// 如果尾节点不为空
if (oldTail != null) {
// 将node节点的prev设置为尾节点
node.setPrevRelaxed(oldTail);
// CAS改变尾节点,若此时尾节点还是oldTail,则将尾节点设为node
if (compareAndSetTail(oldTail, node)) {
// 如果上面操作成功则将以前的尾节点的后一个节点设为新节点
// 否则自旋直至设置node为尾节点成功
oldTail.next = node;
return oldTail;
}
}
// 如果尾节点为空,说明队列为空
else {
// 创建一个队列,即将头和尾设置为同一个新创建的节点
// 然后进入自旋,只有在上面插入成功了才会跳出循环
initializeSyncQueue();
}
}
}
private Node addWaiter(Node mode) {
//Node.EXCLUSIVE 传入null 则创建null 则在下面初始化头尾节点
//Node.SHARED 传入 new Node() 是nextWaiter为 new Node()
Node node = new Node(mode);
for (;;) {
// 获取尾节点
Node oldTail = tail;
// 如果尾节点不为空
if (oldTail != null) {
// CAS改变尾节点,若此时尾节点还是oldTail,则将尾节点设为node
node.setPrevRelaxed(oldTail);
// 使用CAS设置node为尾节点
if (compareAndSetTail(oldTail, node)) {
// 如果上面操作成功则将以前的尾节点的后一个节点设为新节点
// 否则自旋直至设置node为尾节点成功
oldTail.next = node;
return node;
}
} else {
// 创建一个队列,即将头和尾设置为同一个新创建的节点
// 然后进入自旋,只有在上面插入成功了才会跳出循环
initializeSyncQueue();
}
}
}
public final void acquire(int arg) {
// 如果获取锁没有成功 且
if (!tryAcquire(arg) &&
// 先执行addWaiter添加条件队列节点(同时影响AQS队列),独占模式nextWaiter为空
// 然后自旋方法检测排队是否到队头,到了尝试获取锁,没有则设置状态为SIGNEL,并阻塞当前线程
// 自旋方法排队是否到队头,到了尝试获取锁,没有则设置状态为SIGNEL
// 设置成功进行阻塞
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
// 上面是死循环方法而且嵌套在if语句条件中,如果出循环且返回true说明检测到中断状态需要进行自我中断
// 进行自我中断
selfInterrupt();
}
final boolean acquireQueued(final Node node, int arg) {
boolean interrupted = false;
try {
for (;;) {
// 返回node的上一个节点
// 循环后如果node上一个节点改变,则会抛出异常
final Node p = node.predecessor();
// tryAcquire 尝试以独占模式获取
if (p == head && tryAcquire(arg)) {
// 设置该节点为头节点
setHead(node);
// 之前的头节点让GC回收
p.next = null; // help GC
return interrupted;
}
// 独占没有获取成功
// 则尝试设为p的状态为SIGNAL,如果p为要释放节点,则p将往前移
if (shouldParkAfterFailedAcquire(p, node))
// 位操作 | 相当于 逻辑||
// 方便的阻塞方法,然后检查是否中断。
interrupted |= parkAndCheckInterrupt();
}
} catch (Throwable t) {
// 取消获得
// 从队列中移除该节点
cancelAcquire(node);
// 判断是否要添加中断标记
if (interrupted)
selfInterrupt();
throw t;
}
}
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
return true;
if (ws > 0) {
do {
// 跳过中间waitStatus大于0的节点
// pred = pred.prev;
// node.prev = pred;
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
// 设置状态为SIGNAL
pred.compareAndSetWaitStatus(ws, Node.SIGNAL);
}
return false;
}
1.取消当前节点,如果当前结点为空则直接返回
2.如果当前节点存在,则先将其内部线程置空,再往前找状态不大于0的节点存为pred,pred的后一个节点也是要取消的节点存为predNext,设置当前节点状态为CANCELLED
3.使用CAS将尾节点设为前面有效节点pred,成功后再将pred.next置为空
4.CAS操作没有成功则说明此时尾节点已经被替换,说明可能新传入一个节点,此时要判断两个情况,如果pred已经是队头则调用unparkSuccessor唤醒node的后一个节点因为node要被取消了,如果pred不是队头还在排队,则将node下一个节点设为pred的下一个节点,则可以将node从双向链表中移除了
private void cancelAcquire(Node node) {
if (node == null)
return;
//内部线程置空
node.thread = null;
//前找状态不大于0的节点存为prev
Node pred = node.prev;
while (pred.waitStatus > 0)
// pred = pred.prev;
// node.prev = pred
node.prev = pred = pred.prev;
Node predNext = pred.next;
// 设置当前节点状态为CANCELLED
node.waitStatus = Node.CANCELLED;
// 使用CAS将尾节点设为前面有效节点pred,成功后再将pred.next置为空
if (node == tail && compareAndSetTail(node, pred)) {
pred.compareAndSetNext(predNext, null);
}
// CAS操作没有成功则说明此时尾节点已经被替换,说明可能新传入一个节点
else {
int ws;
if (pred != head &&
// 先前一个节点状态为SIGNAL 或
//状态小于0且先前一个节点状态CAS设为SIGNAL(-1)成功且先前一个节点线程不为空
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && pred.compareAndSetWaitStatus(ws, Node.SIGNAL))) &&
pred.thread != null) {
// 获取节点后一个节点
Node next = node.next;
// 如果节点后一个节点非空,且状态小于等于0,则将pred节点的下一个节点设为next节点
if (next != null && next.waitStatus <= 0)
pred.compareAndSetNext(predNext, next);
}
// 如果pred已经是队头
else {
unparkSuccessor(node);
}
node.next = node; // help GC
}
}
private void unparkSuccessor(Node node) {
//获取当前节点状态
int ws = node.waitStatus;
// 如果小于0则是功能节点,将其设为0为普通节点
if (ws < 0)
node.compareAndSetWaitStatus(ws, 0);
Node s = node.next;
// 寻找node后续的有效节点,即不为空且状态不为CANCELLED
if (s == null || s.waitStatus > 0) {
s = null;
// 无效则从尾节点开始找最靠近node的有效节点
for (Node p = tail; p != node && p != null; p = p.prev)
if (p.waitStatus <= 0)
s = p;
}
if (s != null)
// 解除其内部线程阻塞
LockSupport.unpark(s.thread);
}
public final void acquireInterruptibly(int arg)
throws InterruptedException {
//先检测线程是否打上了中断标志,打上了则抛出异常
if (Thread.interrupted())
throw new InterruptedException();
//尝试获取锁没有成功,则
if (!tryAcquire(arg))
// 自旋 循环尝试获取锁,只不过循环一次会阻塞一次,
doAcquireInterruptibly(arg);
}
和acquireQueued类似
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.EXCLUSIVE);
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
return;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} catch (Throwable t) {
cancelAcquire(node);
throw t;
}
}
tryAcquireShared尝试获取共享锁没有成功,则自旋获取
public final void acquireShared(int arg) {
// 尝试获取共享锁没有成功
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
private void doAcquireShared(int arg) {
final Node node = addWaiter(Node.SHARED);
boolean interrupted = false;
try {
for (;;) {
final Node p = node.predecessor();
// 前一节点为头节点
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
return;
}
}
if (shouldParkAfterFailedAcquire(p, node))
interrupted |= parkAndCheckInterrupt();
}
} catch (Throwable t) {
cancelAcquire(node);
throw t;
} finally {
if (interrupted)
selfInterrupt();
}
}
设置node为头节点,并调用doReleaseShared方法唤醒node后续节点
private void setHeadAndPropagate(Node node, int propagate) {
Node h = head;
setHead(node);
if (propagate > 0 || h == null || h.waitStatus < 0 ||
(h = head) == null || h.waitStatus < 0) {
Node s = node.next;
if (s == null || s.isShared())
doReleaseShared();
}
}
private void doReleaseShared() {
for (;;) {
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
if (!h.compareAndSetWaitStatus(Node.SIGNAL, 0))
continue;
//唤醒节点的后续节点(如果存在)。
unparkSuccessor(h);
} else if (ws == 0 &&
!h.compareAndSetWaitStatus(0, Node.PROPAGATE))
continue;
}
if (h == head)
break;
}
}
尝试获取共享锁没有成功则调用doAcquireSharedInterruptibly自旋
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
和doAcquireShared差别不大
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.SHARED);
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} catch (Throwable t) {
cancelAcquire(node);
throw t;
}
}
如果获取独占锁成功则返回,否则自旋获取锁,有超时返回的功能,返回true表示获取成功,返回false表示超时
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
// 如果获取锁成功则返回
return tryAcquire(arg) ||
// 否则自旋获取锁,有超时返回的功能
doAcquireNanos(arg, nanosTimeout);
}
private boolean doAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (nanosTimeout <= 0L)
return false;
final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.EXCLUSIVE);
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
return true;
}
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L) {
cancelAcquire(node);
return false;
}
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException();
}
} catch (Throwable t) {
cancelAcquire(node);
throw t;
}
}
如果获取共享锁成功则返回,否则自旋获取锁,有超时返回的功能,返回true表示获取成功,返回false表示超时
public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
return tryAcquireShared(arg) >= 0 ||
doAcquireSharedNanos(arg, nanosTimeout);
}
private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (nanosTimeout <= 0L)
return false;
final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.SHARED);
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
return true;
}
}
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L) {
cancelAcquire(node);
return false;
}
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > SPIN_FOR_TIMEOUT_THRESHOLD)
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException();
}
} catch (Throwable t) {
cancelAcquire(node);
throw t;
}
}
tryRelease是子类实现的,如果释放独占锁成功,则判断头节点是否为空,不为空则判断头结点状态,如果头结点状态为0,说明已经唤醒过后续结点了,不需要再唤醒,否则则调用unparkSuccessor唤醒后续结点
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
tryRelease是子类实现的,如果释放共享锁成功,则调用doReleaseShared()唤醒后续结点,doReleaseShared代码上面有介绍
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}