public boolean offer(E e) {
checkNotNull(e);
final Node<E> newNode = new Node<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".
if (p != t) // hop two nodes at a time
casTail(t, newNode); // Failure is OK.
return true;
}
// Lost CAS race to another thread; re-read next
}
else if (p == q)
// We have fallen off list. If tail is unchanged, it
// will also be off-list, in which case we need to
// jump to head, from which all live nodes are always
// reachable. Else the new tail is a better bet.
p = (t != (t = tail)) ? t : head;
else
// Check for tail updates after two hops.
p = (p != t && t != (t = tail)) ? t : q;
}
}
我对最后的p = (t != (t = tail)) ? t : head
有些没太看明白,按照执行顺序,先执行括号内的t= tail,然后比较t != t,那不就是始终为true了吗?请问是我哪里理解有问题呢?
这个就是看
(t != (t = tail))
这句话怎么执行的了。简化一下,看下面代码:
这个代码,跟你的代码意思一样的,这样简化比较好理解。
对这个代码的
class文件
进行反编译,查看其字节码
:主要的就在第
0-8
行,逐行分析一下:可以看出,确实在发生比较之前,变量
i
的值已经改变了,但是栈内的元素还是旧值,所以比较还是采用旧值进行比较。同样的道理,只不过你的代码,会改变一些指令,但是基本原理还是这样的。
你的代码比较其实就是比较
t
和tail
,而不是赋值之后的t
。这段代码的意图就是,在当前线程执行这段代码期间,其他线程执行了其他操作,导致链表的尾部对象发生了变化,这个时候重新遍历链表,来重新确定要
offer
的这个对象的位置。