同步器之acquire:
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
先获取同步状态,获取成功方法就结束了,获取失败,才构造节点(addWaiter),以及死循环获取(acquireQueued)
-----------------------------------------------------------------------------------------
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
构造节点node,讲当前尾节点tail赋值给prev,然后判断为尾节点是否为空,为空调用enq方法,不为空的话将构造节点的前驱指向尾节点,然后CAS将构造的节点替换成尾节点,成功之后将前任尾节点(prev)的后继节点设置成构造的节点(node)。
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
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);
}
}
首先,声明2个标志变量,failed(默认就是失败),interrupted(默认非中断);接下来一个死循环获取同步状态。先获取当前节点的前驱,这个节点就是addWaiter构造的节点(),判断当前节点的前驱是否是头节点(每次只允许当构造节点的前驱节点是头结点才去获取同步状态,头结点获取到同步状态的节点),如果是则尝试获取获取同步标志位,获取成功讲当前节点设置成头结点,不需要用CAS因为tryAcquire成功之后确保只会有一个线程调用此方式,将P的Next设置为null,让P出队,(因为当前节点获取到了同步状态,说明P已经释放同步状态)返回中断标志位;如果获取失败则判断当前节点是否该休眠(shouldParkAfterFailedAcquire)parkAndCheckInterrupt方法在当前节点休眠时调用。
-----------------------------------------------------------------------------------------
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/
return true;
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
获取同步状态失败后判断该阶段是否应该睡眠,主要根据的是waitStatus来判断(关于waitStatus的状态意义)。如果前驱节点处于SIGNAL,唤醒状态的。表示当前节点可以安心的休眠。否则判断状态是否大于0(
只有取消状态才会大于0)。如果大于0说明是取消状态,队列中删除该节点,然后取到prev的前驱继续判断,
直到状态不为取消,然后CAS设置节点状态为SINGAL,返回false.[总结一下就是当前节点的前驱节如果是singal状态,就让当前节点休眠,否则判断都不让当前节点休眠]
--------------------------------------------------------------------------------
/** waitStatus value to indicate thread has cancelled */取消状态
static final int CANCELLED = 1;
/** waitStatus value to indicate successor's thread needs unparking */后继节点的线程处于等待状态,当前节点的线程如果释放了同步状态,将会通知后继节点
static final int SIGNAL = -1;
/** waitStatus value to indicate thread is waiting on condition */
节点在等待队列中,节点线程等待在condition,当其他线程对condition调用了singal方法,节点
从等待队列中转移到同步队列中,加入到对同步状态的获取
static final int CONDITION = -2;
/**
* waitStatus value to indicate the next acquireShared should
* unconditionally propagate
*/共享式状态,无条件讲行为传播下去
static final int PROPAGATE = -3;
---------------------------------------------------------------------------------
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
}
看看就好....不写了,具体不写了...
-----------------------------------------------------------------------------------------
private void cancelAcquire(Node node) {
// Ignore if node doesn't exist
if (node == null)
return;
node.thread = null;
// Skip cancelled predecessors
Node pred = node.prev;
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
// predNext is the apparent node to unsplice. CASes below will
// fail if not, in which case, we lost race vs another cancel
// or signal, so no further action is necessary.
Node predNext = pred.next;
// Can use unconditional write instead of CAS here.
// After this atomic step, other Nodes can skip past us.
// Before, we are free of interference from other threads.
node.waitStatus = Node.CANCELLED;
// If we are the tail, remove ourselves.
if (node == tail && compareAndSetTail(node, pred)) {
compareAndSetNext(pred, predNext, null);
} else {
// If successor needs signal, try to set pred's next-link
// so it will get one. Otherwise wake it up to propagate.
int ws;
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
pred.thread != null) {
Node next = node.next;
if (next != null && next.waitStatus <= 0)
compareAndSetNext(pred, predNext, next);
} else {
unparkSuccessor(node);
}
node.next = node; // help GC
}
}
前面判空略过,获取当前节点的前驱节点,如果是取消状态则往前寻找,直到不为取消状态,之后讲当前节点设置为取消状态,判断如果当前节点是尾节点讲前驱CAS设置成尾节点,成功之后CAS设置尾节点的NEXT节点;否则判断pred是否为头节点并且pred状态为唤醒状态或者不为取消状态CAS设置成唤醒状态成功并且pred节点的线程不为空并且node节点的后继不为空位不处于取消状态,CAS将pred的next节点设置成node;否则唤醒当前节点
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
先获取同步状态,获取成功方法就结束了,获取失败,才构造节点(addWaiter),以及死循环获取(acquireQueued)
-----------------------------------------------------------------------------------------
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
构造节点node,讲当前尾节点tail赋值给prev,然后判断为尾节点是否为空,为空调用enq方法,不为空的话将构造节点的前驱指向尾节点,然后CAS将构造的节点替换成尾节点,成功之后将前任尾节点(prev)的后继节点设置成构造的节点(node)。
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
-----------------------------------------------------------------------------------------
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);
}
}
首先,声明2个标志变量,failed(默认就是失败),interrupted(默认非中断);接下来一个死循环获取同步状态。先获取当前节点的前驱,这个节点就是addWaiter构造的节点(),判断当前节点的前驱是否是头节点(每次只允许当构造节点的前驱节点是头结点才去获取同步状态,头结点获取到同步状态的节点),如果是则尝试获取获取同步标志位,获取成功讲当前节点设置成头结点,不需要用CAS因为tryAcquire成功之后确保只会有一个线程调用此方式,将P的Next设置为null,让P出队,(因为当前节点获取到了同步状态,说明P已经释放同步状态)返回中断标志位;如果获取失败则判断当前节点是否该休眠(shouldParkAfterFailedAcquire)parkAndCheckInterrupt方法在当前节点休眠时调用。
-----------------------------------------------------------------------------------------
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
/*
* This node has already set status asking a release
* to signal it, so it can safely park.
*/
return true;
if (ws > 0) {
/*
* Predecessor was cancelled. Skip over predecessors and
* indicate retry.
*/
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
/*
* waitStatus must be 0 or PROPAGATE. Indicate that we
* need a signal, but don't park yet. Caller will need to
* retry to make sure it cannot acquire before parking.
*/
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
获取同步状态失败后判断该阶段是否应该睡眠,主要根据的是waitStatus来判断(关于waitStatus的状态意义)。如果前驱节点处于SIGNAL,唤醒状态的。表示当前节点可以安心的休眠。否则判断状态是否大于0(
只有取消状态才会大于0)。如果大于0说明是取消状态,队列中删除该节点,然后取到prev的前驱继续判断,
直到状态不为取消,然后CAS设置节点状态为SINGAL,返回false.[总结一下就是当前节点的前驱节如果是singal状态,就让当前节点休眠,否则判断都不让当前节点休眠]
--------------------------------------------------------------------------------
/** waitStatus value to indicate thread has cancelled */取消状态
static final int CANCELLED = 1;
/** waitStatus value to indicate successor's thread needs unparking */后继节点的线程处于等待状态,当前节点的线程如果释放了同步状态,将会通知后继节点
static final int SIGNAL = -1;
/** waitStatus value to indicate thread is waiting on condition */
节点在等待队列中,节点线程等待在condition,当其他线程对condition调用了singal方法,节点
从等待队列中转移到同步队列中,加入到对同步状态的获取
static final int CONDITION = -2;
/**
* waitStatus value to indicate the next acquireShared should
* unconditionally propagate
*/共享式状态,无条件讲行为传播下去
static final int PROPAGATE = -3;
---------------------------------------------------------------------------------
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
}
看看就好....不写了,具体不写了...
-----------------------------------------------------------------------------------------
private void cancelAcquire(Node node) {
// Ignore if node doesn't exist
if (node == null)
return;
node.thread = null;
// Skip cancelled predecessors
Node pred = node.prev;
while (pred.waitStatus > 0)
node.prev = pred = pred.prev;
// predNext is the apparent node to unsplice. CASes below will
// fail if not, in which case, we lost race vs another cancel
// or signal, so no further action is necessary.
Node predNext = pred.next;
// Can use unconditional write instead of CAS here.
// After this atomic step, other Nodes can skip past us.
// Before, we are free of interference from other threads.
node.waitStatus = Node.CANCELLED;
// If we are the tail, remove ourselves.
if (node == tail && compareAndSetTail(node, pred)) {
compareAndSetNext(pred, predNext, null);
} else {
// If successor needs signal, try to set pred's next-link
// so it will get one. Otherwise wake it up to propagate.
int ws;
if (pred != head &&
((ws = pred.waitStatus) == Node.SIGNAL ||
(ws <= 0 && compareAndSetWaitStatus(pred, ws, Node.SIGNAL))) &&
pred.thread != null) {
Node next = node.next;
if (next != null && next.waitStatus <= 0)
compareAndSetNext(pred, predNext, next);
} else {
unparkSuccessor(node);
}
node.next = node; // help GC
}
}
前面判空略过,获取当前节点的前驱节点,如果是取消状态则往前寻找,直到不为取消状态,之后讲当前节点设置为取消状态,判断如果当前节点是尾节点讲前驱CAS设置成尾节点,成功之后CAS设置尾节点的NEXT节点;否则判断pred是否为头节点并且pred状态为唤醒状态或者不为取消状态CAS设置成唤醒状态成功并且pred节点的线程不为空并且node节点的后继不为空位不处于取消状态,CAS将pred的next节点设置成node;否则唤醒当前节点