初始化后如何更新java.util.concurrent.ConcurrentLinkedQueue#head?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初始化后如何更新java.util.concurrent.ConcurrentLinkedQueue#head?相关的知识,希望对你有一定的参考价值。

环境:java:java version "1.8.0_201"操作系统:Ubuntu 16.04.6 LTS Linux version 4.15.0-91-generic

最近我阅读了java.util.concurrent.ConcurrentLinkedQueue#offer的源代码,并对下面的代码感到困惑。

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)) {
            ......

初始化ConcurrentLinkedQueue时,itemheadtail为空。

 public ConcurrentLinkedQueue() {
        head = tail = new Node<E>(null);
    }

但是在我第一次调用ConcurrentLinkedQueue#offer之后,代码执行了该行p.casNext(null, newNode)(此处phead是相同的参考),更改了head的参考。p.casNext的细节像这样

        boolean casNext(Node<E> cmp, Node<E> val) {
            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
        }

似乎只有头部的下一个字段被修改,头部的引用如何改变?你能给我些解释吗?预先感谢!

答案

似乎只有头部的下一个字段被修改,头部的参考如何改变?

正确,head.next已更改。

head方法故意不修改队列的offer(e)字段。

headtail字段永远不会是null,因此,当队列为空时,它们都引用相同的节点,并且该节点具有item = null。一个或多个节点具有item = null始终有效。查询或轮询队列时将跳过这些节点。

通过这种方式使代码在不使用锁定的情况下成为线程安全的。

以上是关于初始化后如何更新java.util.concurrent.ConcurrentLinkedQueue#head?的主要内容,如果未能解决你的问题,请参考以下文章

ExecutorService 用例

Java Callable接口的call方法啥时候被调用

java多线程--信号量Semaphore的使用

如何在表初始化后更新 ag-Grid 的 autoGroupColumnDef 属性

初始化后如何更新java.util.concurrent.ConcurrentLinkedQueue#head?

添加行后如何更新 UITableView?