【问题标题】:ConcurrentLinkedQueue Code ExplanationConcurrentLinkedQueue 代码说明
【发布时间】:2013-09-12 19:55:57
【问题描述】:

http://www.java2s.com/Open-Source/Java-Open-Source-Library/7-JDK/java/java/util/concurrent/ConcurrentLinkedQueue.java.htm

以上是ConcurrentLinkedQueue的源码。 我无法理解一种情况。

条件 (p == q) 将如何从 offer 方法进入下面的 sn-p 代码

  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;
        }
    }

还有作者所说的“我们从名单上掉下来”是什么意思

【问题讨论】:

    标签: java multithreading concurrency queue


    【解决方案1】:

    ConcurrentLinkedQueue 允许在遍历内部列表时同时修改它。这意味着您正在查看的节点可能已被同时删除。为了检测这种情况,被移除节点的下一个指针被改变为指向它自己。详情请看updateHead (L302)。

    【讨论】:

    • @Holger : 你能解释一下 concurrentlinkedqueue 的 remove 方法是如何工作的吗?因为当我尝试在多线程环境中理解它时,我错过了一些东西似乎不起作用
    • public boolean remove(Object o) { if (o == null) return false;节点 pred = null; for (Node p = first(); p != null; p = succ(p)) { E item = p.item; if (item != null && o.equals(item) && p.casItem(item, null)) { Node next = succ(p); if (pred != null && next != null) pred.casNext(p, next);返回真; } pred = p; } 返回假; }
    • @Aarish:“它似乎不起作用”是什么意思?
    • @Holger 我尝试在纸上干运行它以供并发线程删除,例如 A -> B -> C -> D-> E 和线程 1 删除 C ,线程 2 删除 D。在这种情况下,如果两个线程使用上述代码切换执行,我最终看不到 B 的 next 指向 E。在这两种情况下, if (pred != null && next != null) 都不会被执行,因为 C 或 D 将为 null。所以我只是想知道如何在并发修改下设置节点的下一个
    • @Aarish:将项目设置为null 不会将下一个指针设置为null。在这段代码中,next 永远不会设置为null。您似乎混淆了项目和节点。
    【解决方案2】:

    条件问“当前节点是否与下一个节点相同?”

    如果是这样,你已经从列表中掉下来了(文档在行。)

    步骤的基本大纲是:

    1. 为提供的数据创建一个新节点。
    2. 遍历列表以找到最后一个节点
    3. 插入新节点作为新尾部。

    if 语句的其他部分正在处理并发修改问题。

    为了更好地理解发生了什么,请阅读 Node.casTail() 和 casNext()

    【讨论】:

    • "条件提出问题“当前节点是否与下一个节点相同?”" 这不是主要问题,因为我们使用下一个节点的原因不是很明显p.next 将等于 p.
    • 这是由于列表的并发修改而可能发生的情况之一。
    • @mawia 你还有什么不清楚的地方吗?如果不是,你可以标记一个已接受的答案或澄清你认为缺少的内容,以便我改进答案吗?
    猜你喜欢
    • 2012-06-25
    • 2017-01-23
    • 2014-09-21
    • 2016-06-01
    • 2015-01-13
    • 2015-08-16
    • 2010-11-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多