1. 父类AbstractOwnableSynchronizer
该类有两个重要的方法,设置独占线程与获取独占线程。
public abstract class AbstractOwnableSynchronizer
implements java.io.Serializable {
/** Use serial ID even though all fields transient. */
private static final long serialVersionUID = 3737899427754241961L;
/**
* 空构造方法
*/
protected AbstractOwnableSynchronizer() { }
/**
* 同步器独占模式当前线程
*/
private transient Thread exclusiveOwnerThread;
/**
* 设置当前独占线程
*/
protected final void setExclusiveOwnerThread(Thread thread) {
exclusiveOwnerThread = thread;
}
/**
* 获取当前独占线程
*/
protected final Thread getExclusiveOwnerThread() {
return exclusiveOwnerThread;
}
}
2. Node节点
用Node作为同步队列和条件队列的节点。
static final class Node {
/** 共享模式中的节点 */
static final Node SHARED = new Node();
/** 独占模式中的节点 */
static final Node EXCLUSIVE = null;
/** 当线程等待超时或者被中断,则取消等待,设等待状态为-1,进入取消状态则不再变化 */
static final int CANCELLED = 1;
/** 后继节点处于等待状态,当前节点(为-1)被取消或者中断时会通知后继节点,使后继节点的线程得以运行 */
static final int SIGNAL = -1;
/** 当前节点处于等待队列,节点线程等待在Condition上,当其他线程对condition执行signall方法时,等待队列转移到同步队列,加入到对同步状态的获取 */
static final int CONDITION = -2;
/**
* 值为-3,与共享模式相关,在共享模式中,该状态标识结点的线程处于可运行状态
*/
static final int PROPAGATE = -3;
/**
* 等待状态
*/
volatile int waitStatus;
/**
* 指向前节点
*/
volatile Node prev;
/**
* 指向后节点
*/
volatile Node next;
/**
* 进入该节点的线程
*/
volatile Thread thread;
/**
* 指向条件队列中的下一个节点
*/
Node nextWaiter;
/**
* 当节点在共享模式中等待时返回true
*/
final boolean isShared() {
return nextWaiter == SHARED;
}
/**
* 返回前一节点
*/
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
Node() { // Used to establish initial head or SHARED marker
}
Node(Thread thread, Node mode) { // 被addWaiter方法调用
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) { // 被条件队列使用
this.waitStatus = waitStatus;
this.thread = thread;
}
}
3. 成员变量
包含三个成员变量,head、tail以及state
/**
* 等待队列的头结点,如果头结点存在的话,它的waitStatus不能是CANCELLED
*/
private transient volatile Node head;
/**
* 等待队列的尾节点
*/
private transient volatile Node tail;
/**
* 同步器状态
*/
private volatile int state;
4. 主要方法
4.1 同步器状态相关
/**
* 获取当前同步器状态
*/
protected final int getState() {
return state;
}
/**
* 设置当前同步器状态
*/
protected final void setState(int newState) {
state = newState;
}
/**
* 调用魔法类的CAS方法,设置同步器状态
*/
protected final boolean compareAndSetState(int expect, int update) {
// See below for intrinsics setup to support this
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
4.2 acquire(int arg)方法
先尝试获取同步状态,如果获取成功(同步状态为0,表示可以获取),直接返回;否则该线程加到等待队列中进行排队。
/**
* 以独占模式获取,忽略中断。 通过调用至少一次tryAcquire(int)实现,成功返回。
* 否则线程排队,可能会重复阻塞和解除阻塞,直到成功才调用tryAcquire(int) 。 该方法可用于实现方法Lock.lock() 。
*/
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
4.3 tryAcquire(int arg)方法
交给子类实现
4.4 addWaiter(Node mode)方法
将新节点加到尾部
/**
* 在尾部添加节点
*/
private Node addWaiter(Node mode) {
// 构建一个新node,nextWaiter是当前node
Node node = new Node(Thread.currentThread(), mode);
// 获取尾结点
Node pred = tail;
// 如果尾节点不为空,将当前节点作为尾结点
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
//尾节点为空,将当前节点入队
enq(node);
return node;
}
4.5 enq(final Node node)方法
将当前节点入队。
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { //尾结点为空,必须初始化
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
4.6 acquireQueued(final Node node, int arg)方法
不断自旋尝试获取同步状态(锁),获取不成功,则阻塞节点中的线程。
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;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt()) // 休眠线程并返回中断状态
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
4.7 release(int arg)方法
在独占模式中释放节点。当返回true的时候,unblocking一个或多个线程。
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
4.8 tryRelease(int arg)方法
尝试释放同步状态,留给子类实现
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
4.9 unparkSuccessor(Node node)方法
唤醒线程
private void unparkSuccessor(Node node) {
// 获取wait状态
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
/**
* 若后继结点为空,或状态为CANCEL(已失效),则从后尾部往前遍历找到最前的一个处于正常阻塞状态的结点
* 进行唤醒
*/
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);//唤醒线程
}
4.10 acquireShared(int arg)方法
在共享模式中获得锁。
public final void acquireShared(int arg) {
if (tryAcquireShared(arg) < 0)
doAcquireShared(arg);
}
4.11 tryAcquireShared(int arg)
尝试获取锁,当返回值大于等于0时,表示能够获取到同步状态,空方法留给子类实现。
4.12 doAcquireShared(int 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; // help GC
if (interrupted)
selfInterrupt();
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
4.13 releaseShared(int arg)方法
该方法在释放同步状态之后,将会唤醒后续处于等待状态的节点。对于能够支持多个线 程同时访问的并发组件(比如Semaphore),它和独占式主要区别在于tryReleaseShared(int arg) 方法必须确保同步状态(或者资源数)线程安全释放,一般是通过循环和CAS来保证的,因为 释放同步状态的操作会同时来自多个线程。
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}