###### 1. 基本原则不变性(fundamental invariants)
``````1.整个队列中一定会存在一个 node(node.next = null), 并且仅存在一个, 但tail引用不一定指向它
2. 队列中所有 item != null 的节点, head一定能够到达; cas 设置 node.item = null, 意味着这个节点被删除
``````
``````不变性(invariants)
1. 所有的有效节点通过 succ() 方法都可达

1. head.item 可能是 null, 也可能不是 null
``````
###### tail 引用的不变性和可变性
``````不变性(invariants)
1. tail 节点通过succ()方法一定到达队列中的最后一个节点(node.next = null)
2. tail != null

1. tail.item 可能是 null, 也可能不是 null
3. tail.next 可能指向 tail
``````

``````1. head 与 tail 都有可能指向一个 (item = null) 的节点
2. 如果 queue 是空的, 则所有 node.item = null
3. queue刚刚创建时 head = tail = dummyNode
4. head/tail 的 item/next 的操作都是通过 CAS
``````

###### 2. 内部节点 Node
``````import com.lami.tuomatuo.search.base.concurrent.unsafe.UnSafeClass;
import sun.misc.Unsafe;

/**
* http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f96a0f/src/share/classes/sun/misc/Unsafe.java
* http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/9b0ca45cd756/src/share/vm/prims/unsafe.cpp
*
* Created by xjk on 1/13/17.
*/
public class Node<E> {
volatile E item;
volatile Node<E> next;

Node(E item){
/**
* Stores a reference value into a given Java variable.
* <p>
* Unless the reference <code>x</code> being stored is either null
* or matches the field type, the results are undefined.
* If the reference <code>o</code> is non-null, car marks or
* other store barriers for that object (if the VM requires them)
* are updated.
* @see #putInt(Object, int, int)
*
* 将 Node 对象的指定 itemOffset 偏移量设置 一个引用值
*/
unsafe.putObject(this, itemOffset, item);
}

boolean casItem(E cmp, E val){
/**
* Atomically update Java variable to <tt>x</tt> if it is currently
* holding <tt>expected</tt>.
* @return <tt>true</tt> if successful
* 原子性的更新 item 值
*/
return unsafe.compareAndSwapObject(this, itemOffset, cmp, val);
}

void lazySetNext(Node<E> val){
/**
* Version of {@link #putObjectVolatile(Object, long, Object)}
* that does not guarantee immediate visibility of the store to
* other threads. This method is generally only useful if the
* underlying field is a Java volatile (or if an array cell, one
* that is otherwise only accessed using volatile accesses).
*
* 调用这个方法和putObject差不多, 只是这个方法设置后对应的值的可见性不一定得到保证,
* 这个方法能起这个作用, 通常是作用在 volatile field上, 也就是说, 下面中的参数 val 是被volatile修饰
*/
unsafe.putOrderedObject(this, nextOffset, val);
}

/**
* Atomically update Java variable to <tt>x</tt> if it is currently
* holding <tt>expected</tt>.
* @return <tt>true</tt> if successful
*
* 原子性的更新 nextOffset 上的值
*
*/
boolean casNext(Node<E> cmp, Node<E> val){
return unsafe.compareAndSwapObject(this, nextOffset, cmp, val);
}

private static Unsafe unsafe;
private static long itemOffset;
private static long nextOffset;

static {
try {
unsafe = UnSafeClass.getInstance();
Class<?> k = Node.class;
itemOffset = unsafe.objectFieldOffset(k.getDeclaredField("item"));
nextOffset = unsafe.objectFieldOffset(k.getDeclaredField("next"));
}catch (Exception e){

}
}
}
``````

``````/** head 节点 */
/** tail 节点 */
private transient volatile Node<E> tail;

/** 默认会构造一个 dummy 节点
* dummy 的存在是防止一些特殊复杂代码的出现
*/
head = tail = new Node<E>(null);
}
``````

###### 4. 查询后继节点方法 succ()
``````/**
* 获取 p 的后继节点, 若 p.next = p (updateHead 操作导致的), 则说明 p 已经 fall off queue, 需要 jump 到 head
*/
final Node<E> succ(Node<E> p){
Node<E> next = p.next;
return (p == next)? head : next;
}
``````

``````/**
* Tries to CAS head to p, If successfully, repoint old head to itself
* as sentinel for succ(), blew
*
* 将节点 p设置为新的节点(这是原子操作),
* 之后将原节点的next指向自己, 直接变成一个哨兵节点(为queue节点删除及garbage做准备)
*
* @param h
* @param p
*/
final void updateHead(Node<E> h, Node<E> p){
if(h != p && casHead(h, p)){
h.lazySetNext(h);
}
}
``````

###### 6. 入队列操作 offer()

``````不变性(invariants)
1. tail 节点通过succ()方法一定到达队列中的最后一个节点(node.next = null)
2. tail != null

1. tail.item 可能是 null, 也可能不是 null
3. tail.next 可能指向 tail
``````

``````/**
* Inserts the specified element at the tail of this queue
* As the queue is unbounded, this method will never return {@code false}
*
* @param e {@code true} (as specified by {@link Queue#offer(Object)})
* @return NullPointerException if the specified element is null
*
* 在队列的末尾插入指定的元素
*/
public boolean offer(E e){
checkNotNull(e);
final Node<E> newNode = new Node<E>(e); // 1. 构建一个 node

for(Node<E> t = tail, p = t;;){ // 2. 初始化变量 p = t = tail
Node<E> q = p.next;  // 3. 获取 p 的next
if(q == null){      // q == null, 说明 p 是 last Node
// p is last node
if(p.casNext(null, newNode)){   // 4. 对 p 进行 cas 操作, newNode -> p.next
// Successful CAS is the linearization point
// for e to become an element of the queue,
// and for newNode to become "live"
if(p != t){ // 5. 每每经过一次 p = q 操作(向后遍历节点), 则 p != t 成立, 这个也说明 tail 滞后于 head 的体现
casTail(t, newNode); // Failure is OK
}
return true;
}
}
else if(p == q){  // 6. (p == q) 成立, 则说明p是pool()时调用 "updateHead" 导致的(删除头节点); 此时说明 tail 指针已经 fallen off queue， 所以进行 jump 操作， 若在t没变化, 则 jump 到 head, 若 t 已经改变(jump操作在另外的线程中执行), 则jump到 head 节点, 直到找到 node.next = null 的节点
/** 1. 大前提 p 是已经被删除的节点
*  2. 判断 tail 是否已经改变
*      1) tail 已经变化, 则说明 tail 已经重新定位
*      2) tail 未变化, 而 tail 指向的节点是要删除的节点, 所以让 p 指向 head
*  判断尾节点是否有变化
*  1. 尾节点变化, 则用新的尾节点
*  2. 尾节点没变化, 将 tail 指向head
*
*  public void test(){
*        String tail = "";
*        String t = (tail = "oldTail");
*        tail = "newTail";
*        boolean isEqual = t != (t = tail); // <- 神奇吧
*        System.out.println("isEqual : "+isEqual); // isEqual : true
*  }
*/
p = (t != (t = tail))? t : head;
}else{
// 7. (p != t) -> 说明执行过 p = q 操作(向后遍历操作), "(t != (t = tail)))" -> 说明尾节点在其他的线程发生变化
// 为什么 "(t != (t = tail)))" 一定要满足呢, 因为 tail变更, 节省了 (p = q) 后 loop 中的无畏操作, tail 更新说明 q节点肯定也是无效的
p = (p != t && (t != (t = tail))) ? t : q;
}
}
}
``````

1. 明明 Node<E> q = p.next, 怎么会有 p = q ?
2. "p = (t != (t = tail))? t : head" 这段代码是什么玩意, 是不是让你直接怀疑自己的java基础了, 不急我们慢慢来.
3. 最后就是 "p = (p != t && (t != (t = tail))) ? t : q"

queue 初始化时是这样的:

state1.png

1） 添加元素 a
1. 由于 head = tail = dummyNode, 所以 p.next = null
2. 直接操作步骤4 (p.casNext(null, newNode)), 若操作成功, 接着往下走, 不成功(并发时 其他的cas操作成功), 再loop 重试至成功
3. 判断 p != t, 这时没出现 tail指向的不是 last node，所以不成立, 直接return

state2.png
1. 添加元素 b
1. 此时还是 head = tail = dummyNode, p节点是 dummyNode, q.item = a, q.item != null 且 q != null, 直接执行步骤7 p = q (p != t && (t != (t = tail)) 下面说)
2. 再次 判断 q == null, 所以 有执行步骤4 p.casNext(), 这时因为执行过 p = q, 所以 p != t 成立, 对tail进行cas操作
3. 最后直接 return
添加 b 之后:
state3.png
1. 添加元素c
1. 这里操作步骤和添加 a 一样, 所以不说了
添加c后:
state4.png

``````1. "p = q", 这是在poll方法中调用 updateHead 方法所致的
2. "p = (t != (t = tail))", 这段代码的意思是 若 tail 节点在另外的节点中有变化 tail != t, 则将 tail 赋值给 p.虽然只有这短短一行代码, 但是包含非常多的意思:
i!= 这个操作符号不是原子的, 它可以被中断;
ii) 执行时 先获取t的值, 再 t = tail, 赋值好了之后再与原来的t比较
iii) 在多线程环境中 tail 很可能在上面添加元素的过程中被改变, 所以会出现 t != tail, 若tail被修改, 则用新的tail, 不然直接跳到head节点
3. 多了一个 p != t , 因为 tail变更, 节省了 (p = q) 后 loop 中的无畏操作, tail 更新说明 q节点肯定也是无效的
``````

OK 至此 整个offer是分析好了, 接下来 poll

###### 7. 出队列操作 poll()

``````不变性(invariants)

1. 所有的有效节点通过 succ() 方法都可达

1. head.item 可能是 null, 也可能不是 null
``````

``````public E poll(){
for(;;){ // 0. 为啥这里面是两个 for 循环? 不防, 你去掉个试试, 其实主要是为了在 "continue restartFromHead" 后进行第二个 for loop 中的初始化
for(Node<E> h = head, p = h, q;;){ // 1.进行变量的初始化 p = h = head,
E item = p.item;

if(item != null && p.casItem(item, null)){  // 2. 若 node.item != null, 则进行cas操作, cas成功则返回值
// Successful CAS is the linearization point
// for item to be removed from this queue
if(p != h){ // hop two nodes at a time  // 3. 若此时的 p != h, 则更新 head(那啥时 p != h, 额, 这个绝对坑啊 -> 执行第8步后)
updateHead(h, ((q = p.next) != null)? q : p); // 4. 进行 cas 更新 head ; "(q = p.next) != null" 怕出现p此时是尾节点了; 在 ConcurrentLinkedQueue 中正真的尾节点只有1个(必须满足node.next = null)
}
return item;
}
else if((q = p.next) == null){  // 5. queue是空的, p是尾节点
updateHead(h, p); // 6. 这一步除了更新head 外, 还是helpDelete删除队列操作, 删除 p 之前的节点(和 ConcurrentSkipListMap.Node 中的 helpDelete 有异曲同工之妙)
return null;
}
else if(p == q){ // 7. p == q -> 说明 p节点已经是删除了的head节点, 为啥呢?(见updateHead方法)
}else
p = q; // 8. 将 q -> p, 进行下个节点的 poll 操作(初始化一个 dummy 节点, 在单线程情况下, 这个 if 判断是第一个执行的)
}
}
}
``````

state4.png
1. poll 第一个元素 a
``````1. 此时 head指向 dummy, tail 指向 item = b 的节点, 所以在步骤2中 item == null, 而 (q = p.next) != null, 所以直接跳到步骤8,
2. 这时 p指向a, 且满足 item != null, 所以执行步骤2, 又因为执行了步骤8, 所以 p != h, 进行 head 节点的更新 (head 指向这时p.next节点)
``````

poll item = a 后:

state6.png
1. poll 第二个元素 b
``````1. 此时 head = tail = b 节点, 所以 item != null, 直接执行 步骤2, 而 p == h , 所以不更新head
``````

poll 节点 b 后:

state7.png
1. poll 第三个元素 c
poll 节点 c 和 poll 节点啊一样的, 所以不说了, 直接看结果图
state8.png

1. ok 这时我们再进行 offer() 节点 d, 则就会出现 offer 中的步骤 6 (p == q), 所以这时p直接跳到 head节点, 来进行更新, 步骤省略....

state9.png