192_如何基于复杂的指针移动完成单向链表的入队?

基于CAS实现的线程并发安全性,非阻塞

LinkedQueue,底层一定是基于链表来实现的,所以一定会有Node类数据结构,Node指向对方串成一个链表,单向的,双向的,head和tail两个指针都是指向了链表中的头节点和尾节点

csharp 复制代码
if (p.casNext(null, newNode)) {
kotlin 复制代码
boolean casNext(Node<E> cmp, Node<E> val) {
    return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
}

这是一个CAS操作,就是把空节点的next指针指向了新的节点,同一时间只有一个线程可以执行成功这个操作

此时如果再次往队列里入队一个李四元素

此时如果再次往队列里入队一个王五元素

arduino 复制代码
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
queue.offer("张三");
queue.offer("李四");
queue.offer("王五");
System.out.println(queue.poll());
System.out.println(queue);
csharp 复制代码
public ConcurrentLinkedQueue() {
    head = tail = new Node<E>(null);
}
arduino 复制代码
private static class Node<E> {
    volatile E item;
    volatile Node<E> next;

    /**
     * Constructs a new node.  Uses relaxed write because item can
     * only be seen after publication via casNext.
     */
    Node(E item) {
        UNSAFE.putObject(this, itemOffset, item);
    }

    boolean casItem(E cmp, E val) {
        return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
    }

    void lazySetNext(Node<E> val) {
        UNSAFE.putOrderedObject(this, nextOffset, val);
    }

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

    // Unsafe mechanics

    private static final sun.misc.Unsafe UNSAFE;
    private static final long itemOffset;
    private static final long nextOffset;

    static {
        try {
            UNSAFE = sun.misc.Unsafe.getUnsafe();
            Class<?> k = Node.class;
            itemOffset = UNSAFE.objectFieldOffset
                (k.getDeclaredField("item"));
            nextOffset = UNSAFE.objectFieldOffset
                (k.getDeclaredField("next"));
        } catch (Exception e) {
            throw new Error(e);
        }
    }
}
scss 复制代码
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;
    }
}
相关推荐
yhole4 分钟前
springboot 修复 Spring Framework 特定条件下目录遍历漏洞(CVE-2024-38819)
spring boot·后端·spring
BingoGo9 分钟前
Laravel 13 正式发布 使用 Laravel AI 无缝平滑升级
后端·php
l软件定制开发工作室25 分钟前
Spring开发系列教程(34)——打包Spring Boot应用
java·spring boot·后端·spring·springboot
随风,奔跑28 分钟前
Spring MVC
java·后端·spring
美团技术团队1 小时前
美团 BI 在指标平台和分析引擎上的探索和实践
后端
JimmtButler1 小时前
我用 Claude Code 给 Claude Code 做了一个 DevTools
后端·claude
Java水解1 小时前
Java 中实现多租户架构:数据隔离策略与实践指南
java·后端
Master_Azur2 小时前
Java面向对象之多态与重写
后端
ywf12152 小时前
Spring Integration + MQTT
java·后端·spring
武超杰3 小时前
SpringMVC核心功能详解:从RESTful到JSON数据处理
后端·json·restful