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;
    }
}
相关推荐
立心者01 小时前
SpringBoot中使用TOTP实现MFA(多因素认证)
java·spring boot·后端
AskHarries1 小时前
SEO 页面怎么生成
后端
爱吃牛肉的大老虎2 小时前
Rust对象之结构体,枚举,特性
开发语言·后端·rust
石榴2 小时前
NestJS 的请求到底经过了什么:装饰器、守卫、拦截器、管道与中间件如何配合
后端
Gopher_HBo2 小时前
moby-client客户端
后端
杨运交2 小时前
[055][调度模块]Spring动态任务调度框架的设计与实现
java·后端·spring
卷福同学4 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端
Csvn5 小时前
📊 SQL 入门 Day 11:CASE 表达式:SQL 里的 if-else 魔法
后端·sql
QQ_21696290965 小时前
Spring Boot 养老院管理系统:从入住、护理到费用结算的全流程实现(源码可领)
java·spring boot·后端
万少7 小时前
DeepSeek-V4-Flash 正式版上线了,但这 3 个坑我帮你提前踩了
前端·javascript·后端