猿问

JDK 源码理解问题

小弟最近在翻看JDK的源码但是奈何基础太差有一处始终想不通。希望大家帮忙解答下共同进步。


ConcurrentLinkedQueue的源码中的offer方法

 (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

            }

            )

我的理解是 既然t = p; 那么对p的操作应该等同与对t的操作,那么将newNode设置为p.next不久等同于对t也设置next属性么, 为什么p!=t呢?


繁星coding
浏览 576回答 2
2回答

侃侃尔雅

就一个线程在处理的话肯定不会走casTail这句,如果有多个线程呢?&nbsp; &nbsp; public boolean offer(E e) {&nbsp; &nbsp; &nbsp; &nbsp; checkNotNull(e);&nbsp; &nbsp; &nbsp; &nbsp; final Node<E> newNode = new Node<E>(e);&nbsp; &nbsp; &nbsp; &nbsp; for (Node<E> t = tail, p = t;;) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//如果2个线程到这里,一个先把流程走完了&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//第二个线程的q开始执行的时候已经不是null了&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//所以会走else的分支,修改了p和t的关系&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Node<E> q = p.next;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (q == null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // p is last node&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (p.casNext(null, newNode)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Successful CAS is the linearization point&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // for e to become an element of this queue,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // and for newNode to become "live".&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (p != t) // hop two nodes at a time&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; casTail(t, newNode);&nbsp; // Failure is OK.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Lost CAS race to another thread; re-read next&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else if (p == q)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // We have fallen off list.&nbsp; If tail is unchanged, it&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // will also be off-list, in which case we need to&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // jump to head, from which all live nodes are always&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // reachable.&nbsp; Else the new tail is a better bet.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p = (t != (t = tail)) ? t : head;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Check for tail updates after two hops.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p = (p != t && t != (t = tail)) ? t : q;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }

ibeautiful

当两个线程同时 进入 q == null 判断逻辑的时候 ,其中一个线程完成了CAS操作以后,另一个线程会重新循环,这时候会走到 p = (p != t && t != (t = tail)) ? t : q; 这个操作 (ide中 是走到了 else if (p == q) 这个操作 , 不知道eclispe 和 idea为啥最终进入的方法不一样,希望高人能解答下),这时候p重新赋值了,然后 继续循环 到 q == null 这个逻辑,这时候p!=t 了 .
随时随地看视频慕课网APP

相关分类

Java
我要回答