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; }
如果队列没被初始化就会再实例一个thread为null的node对象并将它设置为aqs的头和尾
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
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; } } } }
privatestaticbooleanshouldParkAfterFailedAcquire(Node pred, Node node){ int ws = pred.waitStatus; // 上一节点的ws=0 if (ws == Node.SIGNAL) // -1 /* * This node has already set status asking a release * to signal it, so it can safely park. */ returntrue; 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); //将前一个节点的ws状态设置为-1 } returnfalse; }
if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); returntrue; }
1 2 3 4 5 6 7 8 9 10
publicfinalbooleanhasQueuedPredecessors(){ // The correctness of this depends on head being initialized // before tail and on head.next being accurate if the current // thread is first in queue. Node t = tail; // Read fields in reverse initialization order Node h = head; Node s; return h != t && ((s = h.next) == null || s.thread != Thread.currentThread()); }
如果已经被初始化又可以分为队列中元素大于一和队列中元素等于一两种情况,先说大于一的情况。队列中元素大于一 h != t 就返回true继续向下,既然队列元素大于一那(s =h.next) == null必然不成立,为什么这里还有个这个判断呢因为 h != t 不是原子操作在执行这行代码时队列中可能已经出队只剩下一个元素了。不过这种情况应该不大概率出现但是不得不说Doug Lea考虑的是真的周全。回到正题 (s =h.next) == null 等于false继续执行s.thread != Thread.currentThread() 这里是判断当前来询问的线程是否是位于队列排队第一的线程如果是就返回false整体返回false加上!得true执行cas加锁,如果不是位于第一的线程他就没有加锁的资格s.thread != Thread.currentThread()就返回true整体返回true加上!得false就不加锁,叫它继续睡还没轮到它。那什么情况下队列中只有一个元素呢,当整个队列队尾拿到锁的时候,就只有它一个元素h != t因为只有它一个所以头尾都是它,此处返回false不再继续执行整体返回false然后取反得到true执行cas加锁。