AbstractQueuedSynchronizer
AbstractQueuedSynchronizer为实现依赖于先进先出 (FIFO) 等待队列的阻塞锁定和相关同步器(信号量、事件,等等)提供一个框架。此类的设计目标是成为依靠单个原子 int 值来表示状态的大多数同步器的一个有用基础。子类必须定义更改此状态的受保护方法,并定义哪种状态对于此对象意味着被获取或被释放。假定这些条件之后,此类中的其他方法就可以实现所有排队和阻塞机制。但只是为了获得同步而只追踪使用 getState()、setState(int) 和 compareAndSetState(int, int) 方法来操作以原子方式更新的 int 值。
1.锁持有者管理AbstractOwnableSynchronizer
/**
* 锁持有者管理器 抽象类 -- 设置 和 获取独占锁的拥有者线程
*/
public abstract class AbstractOwnableSynchronizer implements java.io.Serializable {
private static final long serialVersionUID = 3737899427754241961L;
protected AbstractOwnableSynchronizer() { }
/** 锁持有者的线程 */
private transient Thread exclusiveOwnerThread;
/**
* 设置锁持有者的线程
* @param thread
*/
protected final void setExclusiveOwnerThread(Thread thread) {
exclusiveOwnerThread = thread;
}
/**
* 获取锁持有者的线程
*/
protected final Thread getExclusiveOwnerThread() {
return exclusiveOwnerThread;
}
}
2.阻塞队列里的节点定义AbstractQueuedSynchronizer.Node
/** 阻塞队列里的节点定义 */
static final class Node {
static final Node SHARED = new Node(); //共享状态
static final Node EXCLUSIVE = null; //互斥状态
static final int CANCELLED = 1; //值为1,被取消的,在等待队列中等待的线程超时或被中断,进入该状态的节点的将不再变化
static final int SIGNAL = -1; //值为-1,当前节点在入队后、进入休眠状态前,应确保将其prev节点类型改为SIGNAL,以便后者取消或释放时将当前节点唤醒
static final int CONDITION = -2; //值为-2,该节点处于条件队列中,当其他线程调用了Condition的signal()方法后,节点转移到AQS的等待队列中,特别要注意的是,条件队列和AQS的等待队列并不是一回事
static final int PROPAGATE = -3; //WaistStand值指示下一个获取应该无条件传播
/** WaistStand值为0这里没写,为0也算是一种状态,但不是上面所有的,表示没有被任何锁拥有 */
volatile int waitStatus; //等待状态
volatile Node prev; //前一个node
volatile Node next; //后一个node
volatile Thread thread; //在node里面的线程
Node nextWaiter; //下一个正处在等待条件的node
/**如果在等待node在共享模式下返回true*/
final boolean isShared() {
return nextWaiter == SHARED;
}
/**返回前一个node。如果为空返回空指针异常*/
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
/** 用于建立初始标记或共享标记 */
Node() {
}
/** 给线程添加等待模型,生成node */
Node(Thread thread, Node mode) {
this.nextWaiter = mode;
this.thread = thread;
}
/** 给线程添加等待条件,生成node */
Node(Thread thread, int waitStatus) {
this.waitStatus = waitStatus;
this.thread = thread;
}
}
3.CAS实现
/**
* 引入unsafe类
* 通过unsafe.objectFieldOffset获取字段对应的偏移量
*/
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long stateOffset;
private static final long headOffset;
private static final long tailOffset;
private static final long waitStatusOffset;
private static final long nextOffset;
static {
try {
/**
* class.getDeclaredField(String fieldName) 获取class中fieldName对应的字段
* unsafe.objectFieldOffset(Field field) 获取字段field在类中对应的地址偏移量
*/
stateOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("state")); //同步的状态
headOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("head")); //等待队列头节点
tailOffset = unsafe.objectFieldOffset
(AbstractQueuedSynchronizer.class.getDeclaredField("tail")); //等待队列尾节点
waitStatusOffset = unsafe.objectFieldOffset
(Node.class.getDeclaredField("waitStatus"));
nextOffset = unsafe.objectFieldOffset
(Node.class.getDeclaredField("next"));
} catch (Exception ex) { throw new Error(ex); }
}
/** 用到CAS进行原子更新。如果当前状态值等于预期值,则以原子方式将同步状态设置为给定的更新值。 */
private final boolean compareAndSetHead(Node update) { //设置state null -- update
return unsafe.compareAndSwapObject(this, headOffset, null, update);
}
private final boolean compareAndSetTail(Node expect, Node update) { //设置tail expect -- update
return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
}
private static final boolean compareAndSetWaitStatus(Node node, int expect, int update) {//设置waitStatus expect -- update
return unsafe.compareAndSwapInt(node, waitStatusOffset, expect, update);
}
private static final boolean compareAndSetNext(Node node, Node expect, Node update) {//设置next expect -- update
return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
}
/** 调用unsafe自选操作将state的值更新 返回是否操作成功 */
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
4.预留方法待子类实现
/**
* 尝试获取锁 待子类实现
*/
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
/**
* 尝试释放锁 待子类实现
*/
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
/**
* 尝试获取共享资源 待子类实现 返回负数未失败 其他为成功
*/
protected int tryAcquireShared(int arg) {
throw new UnsupportedOperationException();
}
/**
* 共享模式尝试释放锁
*/
protected boolean tryReleaseShared(int arg) {
throw new UnsupportedOperationException();
}
/**
* 在独占模式下,状态是否被占用
*/
protected boolean isHeldExclusively() {
throw new UnsupportedOperationException();
}
5.acquire
/**
* 获取独占锁,对中断不敏感。
* 首先尝试获取一次锁,如果成功,则返回;
* 否则会把当前线程包装成Node插入到队列中,在队列中会检测是否为head的直接后继,并尝试获取锁,
* 如果获取失败,则会通过LockSupport阻塞当前线程,直至被释放锁的线程唤醒或者被中断,随后再次尝试获取锁,如此反复。
*/
public final void acquire(int arg) {
if (!tryAcquire(arg) && //尝试获取锁 --子类实现
acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) //放入队列 尝试获取锁
selfInterrupt();
}
/**
* 在队列中的节点通过此方法获取锁,对中断不敏感。
*/
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) { //循环操作
final Node p = node.predecessor(); //获取node的前一个节点
/*检测当前节点前驱是否head,这是尝试试获取锁的资格。
* 如果是的话,则调用tryAcquire尝试获取锁,
* 成功,则将head置为当前节点。
*/
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted; //锁获取成功 返回interrupted
}
/*如果未成功获取锁则根据前驱节点判断是否要阻塞。
* 如果阻塞过程中被中断,则置interrupted标志位为true。
* shouldParkAfterFailedAcquire方法在前驱状态不为SIGNAL的情况下都会循环重试获取锁。
*/
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
/**返回前一个node。如果为空返回空指针异常*/
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
/**
* 设置node到队列的头,去排队,返回当前node,头节点只是一个节点,里面没有线程
* 注意:就算你添加的node是全的,进入队头线程就会被置为空
*/
private void setHead(Node node) {
head = node;
node.thread = null;
node.prev = null;
}
/**
* 根据前驱节点中的waitStatus来判断是否需要阻塞当前线程。
*/
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL) //前驱节点设置为SIGNAL状态,在释放锁的时候会唤醒后继节点,所以后继节点(也就是当前节点)现在可以阻塞自己。
return true;
if (ws > 0) { //前驱节点状态为取消
//向前遍历,更新当前节点的前驱为往前第一个非取消节点。当前线程会之后会再次回到循环并尝试获取锁。
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
/*
* 等待状态为0或者PROPAGATE(-3),设置前驱的等待状态为SIGNAL,
* 并且之后会回到循环再次重试获取锁。
*/
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
/**
* 清除线程中断状态
*/
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
/**
* 该方法实现某个node取消获取锁。
*/
private void cancelAcquire(Node node) {
if (node == null)
return;
node.thread = null;
// 遍历并更新节点前驱,把node的prev指向前部第一个非取消节点
Node pred = node.prev;
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
// 记录pred节点的后继为predNext,后续CAS会用到。
Node predNext = pred.next;
// 直接把当前节点的等待状态置为取消,后继节点即便也在cancel可以跨越node节点
node.waitStatus = Node.CANCELLED;
/**
* 如果CAS将tail从node置为pred节点了
* 则剩下要做的事情就是尝试用CAS将pred节点的next更新为null以彻底切断pred和node的联系。
* 这样一来就断开了pred与pred的所有后继节点,这些节点由于变得不可达,最终会被回收掉。
* 由于node没有后继节点,所以这种情况到这里整个cancel就算是处理完毕了。
* 这里的CAS更新pred的next即使失败了也没关系,说明有其它新入队线程或者其它取消线程更新掉了。
*/
if (node == tail && compareAndSetTail(node, pred)) {
compareAndSetNext(pred, predNext, null);
} else {
//如果node还有后继节点,这种情况要做的事情是把pred和后继非取消节点拼起来。
int ws;
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
pred.thread != null) {
Node next = node.next;
/*
* 如果node的后继节点next非取消状态的话,则用CAS尝试把pred的后继置为node的后继节点
* 这里if条件为false或者CAS失败都没关系,这说明可能有多个线程在取消,总归会有一个能成功的。
*/
if (next != null && next.waitStatus <= 0)
compareAndSetNext(pred, predNext, next);
} else {
/*
* 这时说明pred == head或者pred状态取消或者pred.thread == null
* 在这些情况下为了保证队列的活跃性,需要去唤醒一次后继线程。
* 举例来说pred == head完全有可能实际上目前已经没有线程持有锁了,
* 自然就不会有释放锁唤醒后继的动作。如果不唤醒后继,队列就挂掉了。
*
* 这种情况下看似由于没有更新pred的next的操作,队列中可能会留有一大把的取消节点。
* 实际上不要紧,因为后继线程唤醒之后会走一次试获取锁的过程,
* 失败的话会走到shouldParkAfterFailedAcquire的逻辑。
* 那里面的if中有处理前驱节点如果为取消则维护pred/next,踢掉这些取消节点的逻辑。
*/
unparkSuccessor(node);
}
/*
* 取消节点的next之所以设置为自己本身而不是null,
* 是为了方便AQS中Condition部分的isOnSyncQueue方法,
* 判断一个原先属于条件队列的节点是否转移到了同步队列。
*
* 因为同步队列中会用到节点的next域,取消节点的next也有值的话,
* 可以断言next域有值的节点一定在同步队列上。
*
* 在GC层面,和设置为null具有相同的效果。
*/
node.next = node; // help GC
}
}
6.acquireInterruptibly
/**
* 以独占方式获得,如果中断,中止。 首先检查中断状态
*/
public final void acquireInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted()) //若线程已被中断 抛出异常
throw new InterruptedException();
if (!tryAcquire(arg)) //尝试获取锁
doAcquireInterruptibly(arg); //获取锁失败操作 线程排队
}
/**
* 独占模式 线程排队 循环获取锁 会响应中断
*/
private void doAcquireInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.EXCLUSIVE); //新建节点放入队列
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor(); //获取前一个节点
if (p == head && tryAcquire(arg)) { //调用tryAcquire(int)直到成功或线程中断
setHead(node); //获取锁成功node设置为头节点 清空信息
p.next = null;
failed = false; //设置取消设置标识为false
return;
}
if (shouldParkAfterFailedAcquire(p, node) && //是否需要阻塞当前线程
parkAndCheckInterrupt()) //获取线程中断状态并清除中断状态
throw new InterruptedException(); //当前线程需要阻塞 但却已经中断 抛出异常结束循环
}
} finally {
if (failed) //是否取消获取锁
cancelAcquire(node); //线程中断 取消获取锁
}
}
7.tryAcquireNanos
/**
* 尝试以独占模式获取,如果中断则中止,如果给定的超时时间失败
*/
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
return tryAcquire(arg) ||
doAcquireNanos(arg, nanosTimeout);
}
/**
* 处理方式同doAcquireInterruptibly 多限制了等待时长
*/
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);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return true;
}
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L) //是否超时
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException(); //响应中断
}
} finally {
if (failed)
cancelAcquire(node);
}
}
8.acquireShared
/**
* 共享模式获取锁
*/
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0) //未获取成功
doAcquireShared(arg);
}
/**
* 共享模式 线程排队 循环获取锁 对中断不敏感
*/
private void doAcquireShared(int arg) {
final Node node = addWaiter(Node.SHARED); //添加节点
boolean failed = true; //是否进行取消锁操作
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor(); //获取前一个节点
if (p == head) {
int r = tryAcquireShared(arg); //尝试获取锁
if (r >= 0) { //获取成功
setHeadAndPropagate(node, r);
p.next = null;
if (interrupted) //是否要中断
selfInterrupt(); //中断当前线程
failed = false; //不需要取消获取锁
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&//是否需要阻塞当前线程
parkAndCheckInterrupt()) //获取线程中断状态并清除中断状态
interrupted = true; //设置中断为false
}
} finally {
if (failed)
cancelAcquire(node);//线程中断 取消获取锁
}
}
9.acquireSharedInterruptibly
/**
* 以共享方式获取,如果中断,中止。首先检查中断状态
*/
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);
boolean failed = true;
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
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
10.tryAcquireSharedNanos
/**
* 尝试以共享模式获取,如果中断则中止,如果给定的时间超过,则失败
*/
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);
boolean failed = true;
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
failed = false;
return true;
}
}
nanosTimeout = deadline - System.nanoTime();
if (nanosTimeout <= 0L)
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
if (Thread.interrupted())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
11.releaseShared
/**
* 共享模式 释放资源并唤醒等待中的队列
*/
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) { //尝试释放资源
doReleaseShared();
return true;
}
return false;
}
/**
* 释放共享模式,从头部开始的第一个需要信号(被唤醒)的node释放,确保传播。
* 注意:对于互斥模式,如果需要被唤醒,相当于调用unpackSuccessor()的头部
*/
private void doReleaseShared() {
for (;;) {
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
continue; // loop to recheck cases
unparkSuccessor(h);
}
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
if (h == head) // loop if head changed
break;
}
}
12.LockSupport
/**
* LockSupport是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞或唤醒
*/
@SuppressWarnings("unused")
public class LockSupport {
private LockSupport() {} // Cannot be instantiated.
private static void setBlocker(Thread t, Object arg) {
UNSAFE.putObject(t, parkBlockerOffset, arg);
}
/** 恢复当前线程 */
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
/** 暂停当前线程 */
public static void park() {
UNSAFE.park(false, 0L);
}
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
}
/** 暂停当前线程,不过有超时时间的限制 */
public static void parkNanos(long nanos) {
if (nanos > 0)
UNSAFE.park(false, nanos);
}
public static void parkNanos(Object blocker, long nanos) {
if (nanos > 0) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, nanos);
setBlocker(t, null);
}
}
/** 暂停当前线程,直到某个时间 */
public static void parkUntil(long deadline) {
UNSAFE.park(true, deadline);
}
public static void parkUntil(Object blocker, long deadline) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(true, deadline);
setBlocker(t, null);
}
public static Object getBlocker(Thread t) {
if (t == null)
throw new NullPointerException();
return UNSAFE.getObjectVolatile(t, parkBlockerOffset);
}
static final int nextSecondarySeed() {
int r;
Thread t = Thread.currentThread();
if ((r = UNSAFE.getInt(t, SECONDARY)) != 0) {
r ^= r << 13; // xorshift
r ^= r >>> 17;
r ^= r << 5;
}
else if ((r = java.util.concurrent.ThreadLocalRandom.current().nextInt()) == 0)
r = 1; // avoid zero
UNSAFE.putInt(t, SECONDARY, r);
return r;
}
private static final sun.misc.Unsafe UNSAFE;
private static final long parkBlockerOffset;
private static final long SEED;
private static final long PROBE;
private static final long SECONDARY;
static {
try {
UNSAFE = sun.misc.Unsafe.getUnsafe();
Class<?> tk = Thread.class;
parkBlockerOffset = UNSAFE.objectFieldOffset
(tk.getDeclaredField("parkBlocker"));
SEED = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomSeed"));
PROBE = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomProbe"));
SECONDARY = UNSAFE.objectFieldOffset
(tk.getDeclaredField("threadLocalRandomSecondarySeed"));
} catch (Exception ex) { throw new Error(ex); }
}
}