publicbooleanoffer(E e) { checkNotNull(e); final Node<E> newNode = newNode<E>(e);
for (Node<E> t = tail, p = t;;) { Node<E> q = p.next; if (q == null) { // p is last node if (p.casNext(null, newNode)) { // Successful CAS is the linearization point // for e to become an element of this queue, // and for newNode to become "live". // 因为tail的滞后性 ,并不会随时随地的修改tail,只有当tail指针与真实的尾节点 // 距离相差超过1时 才会进行更新。 该操作如果失败,说明有其他线程执行成功,所以不需重试 if (p != t) // hop two nodes at a time casTail(t, newNode); // Failure is OK. returntrue; } // Lost CAS race to another thread; re-read next } // 当执行 poll 或 remove操作时,会有这种情况产生 elseif (p == q) // p == q 说明p变成来哨兵节点(即被poll删除了) 因此需要判断t的执行是否与当前的tail节点一致 // 如果一致,说明tail被删除了,那么需要从头开始遍历 ,如果不一致,那么直接从当前尾节点继续遍历 p = (t != (t = tail)) ? t : head; else // 只有offer操作 会执行到这里 // 1. 当有两个线程(A B) 竞争时, 如果A 添加了尾节点 ,那么B会在第二次循环时走到这里(因为p.next 已经不为null),此时 p == t 所以 p 指向 q 然后在下一轮更新 赋值
// 2. 如果又有C线程竞争 ,因为执行完1后,线程B 在添加尾节点时有竞争失败,那么继续走到这里,此时 p 已经执行 q,即 p != t, 而如果 tail被其他线程改变了,那么p = t(这时的t已经指向了新的tail) 然后开始新一轮的循环 p = (p != t && t != (t = tail)) ? t : q; } }