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

问题描述 投票:0回答:1

环境: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);
        }

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

java cas
1个回答
0
投票

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

正确,head.next已更改。

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.