@huangyichun
        
        2017-08-30T08:07:54.000000Z
        字数 8218
        阅读 1050
    多线程
//同步器状态private volatile int state;//设置当前同步状态protected final void setState(int newState) {state = newState;}//采用CAS算法更新state状态protected final boolean compareAndSetState(int expect, int update) {// See below for intrinsics setup to support thisreturn unsafe.compareAndSwapInt(this, stateOffset, expect, update);}
static final class Node {//标记节点的等待模式为共享型模式static final Node SHARED = new Node();//标记节点的等待模式为独占型模式static final Node EXCLUSIVE = null;/** 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 */static final int CONDITION = -2;/*** waitStatus value to indicate the next acquireShared should* unconditionally propagate*/static final int PROPAGATE = -3;/*** Status field, taking on only the values:* SIGNAL: The successor of this node is (or will soon be)* blocked (via park), so the current node must* unpark its successor when it releases or* cancels. To avoid races, acquire methods must* first indicate they need a signal,* then retry the atomic acquire, and then,* on failure, block.* CANCELLED: This node is cancelled due to timeout or interrupt.* Nodes never leave this state. In particular,* a thread with cancelled node never again blocks.* CONDITION: This node is currently on a condition queue.* It will not be used as a sync queue node* until transferred, at which time the status* will be set to 0. (Use of this value here has* nothing to do with the other uses of the* field, but simplifies mechanics.)* PROPAGATE: A releaseShared should be propagated to other* nodes. This is set (for head node only) in* doReleaseShared to ensure propagation* continues, even if other operations have* since intervened.* 0: None of the above** The values are arranged numerically to simplify use.* Non-negative values mean that a node doesn't need to* signal. So, most code doesn't need to check for particular* values, just for sign.** The field is initialized to 0 for normal sync nodes, and* CONDITION for condition nodes. It is modified using CAS* (or when possible, unconditional volatile writes).*/volatile int waitStatus;/*** Link to predecessor node that current node/thread relies on* for checking waitStatus. Assigned during enqueuing, and nulled* out (for sake of GC) only upon dequeuing. Also, upon* cancellation of a predecessor, we short-circuit while* finding a non-cancelled one, which will always exist* because the head node is never cancelled: A node becomes* head only as a result of successful acquire. A* cancelled thread never succeeds in acquiring, and a thread only* cancels itself, not any other node.*/volatile Node prev;/*** Link to the successor node that the current node/thread* unparks upon release. Assigned during enqueuing, adjusted* when bypassing cancelled predecessors, and nulled out (for* sake of GC) when dequeued. The enq operation does not* assign next field of a predecessor until after attachment,* so seeing a null next field does not necessarily mean that* node is at end of queue. However, if a next field appears* to be null, we can scan prev's from the tail to* double-check. The next field of cancelled nodes is set to* point to the node itself instead of null, to make life* easier for isOnSyncQueue.*/volatile Node next;/*** 获取同步状态的线程*/volatile Thread thread;/***等待队列中的后继节点。如果当前节点是共享的,那么这个字段将是一个SHARED常量*也就是说节点类型和等待队列中的后继节点共用一个字段*/Node nextWaiter;/*** Returns true if node is waiting in shared mode.*/final boolean isShared() {return nextWaiter == SHARED;}/*** Returns previous node, or throws NullPointerException if null.* Use when predecessor cannot be null. The null check could* be elided, but is present to help the VM.** @return the predecessor of this node*/final Node predecessor() throws NullPointerException {Node p = prev;if (p == null)throw new NullPointerException();elsereturn p;}Node() { // Used to establish initial head or SHARED marker}Node(Thread thread, Node mode) { // Used by addWaiterthis.nextWaiter = mode;this.thread = thread;}Node(Thread thread, int waitStatus) { // Used by Conditionthis.waitStatus = waitStatus;this.thread = thread;}}
加入过程由于有多个线程可能会同时参与,所以需要同步器提供一个基于CAS的设置尾方法:compareAndSetTail(Node expect, Node update),它需要传递当前线程"认为"的尾节点和当前节点,只有设置成功后,当前节点才正式与之前的尾节点建立连接。
同步队列遵循FIFO,首节点是获取同步状态成功的节点。首节点的线程在释放同步状态时,会唤醒后继节点,而后继节点将会在获取同步状态成功时将自己设置成首节点,由于只有一个线程参与所以不用CAS保证,它只需将首节点设置为原首节点的后继节点并断开原首节点的next引用即可。
private void setHead(Node node) {head = node;node.thread = null;node.prev = null;}
public final void acquire(int arg) {if (!tryAcquire(arg) &&acquireQueued(addWaiter(Node.EXCLUSIVE), arg))selfInterrupt();}//保证线程安全的获取同步状态,该方法需要重写protected boolean tryAcquire(int arg) {throw new UnsupportedOperationException();}//添加同步节点private Node addWaiter(Node mode) {Node node = new Node(Thread.currentThread(), mode);//构造同步节点// Try the fast path of enq; backup to full enq on failureNode pred = tail;if (pred != null) {//如果队列不为空node.prev = pred;if (compareAndSetTail(pred, node)) {//在尾部添加节点pred.next = node;return node; //返回节点}}enq(node); //队列为空return node;}private Node enq(final Node node) {for (;;) {//无限循环Node t = tail;if (t == null) { // Must initializeif (compareAndSetHead(new Node()))//添加一个空的节点,作为头节点tail = head;} else {node.prev = t;if (compareAndSetTail(t, node)) {//将节点插入到末尾,CAS算法保障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 GCfailed = false;return interrupted;}if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())//线程进入等待状态interrupted = true;}} finally {if (failed)cancelAcquire(node);}}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;}
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);}
具体流程图在Java并发编程的艺术P128页
共享式同步状态获取与释放最主要的区别在于同一时刻能否有多个线程同时获取到同步状态。
//尝试获取同步状态,当返回值大于等于0时,表示可以获取同步状态public final void acquireShared(int arg) {if (tryAcquireShared(arg) < 0)doAcquireShared(arg);}//需要自己实现protected int tryAcquireShared(int arg) {throw new UnsupportedOperationException();}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 GCif (interrupted)selfInterrupt();failed = false;return;}}if (shouldParkAfterFailedAcquire(p, node) &&parkAndCheckInterrupt())interrupted = true;}} finally {if (failed)cancelAcquire(node);}}
//初始节点private transient Node firstWaiter;//尾节点private transient Node lastWaiter;//将以当前线程构造节点,并将节点从尾部加入等待队列//不需要CAS保证,因为调用await()方法的线程必定是获取了锁的线程public final void await() throws InterruptedException {if (Thread.interrupted())throw new InterruptedException();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 cancelledunlinkCancelledWaiters();if (interruptMode != 0)reportInterruptAfterWait(interruptMode);}
未完待续。。。