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;
    }
}
相关推荐
80530单词突击赢5 小时前
JavaWeb进阶:SpringBoot核心与Bean管理
java·spring boot·后端
爬山算法5 小时前
Hibernate(87)如何在安全测试中使用Hibernate?
java·后端·hibernate
WeiXiao_Hyy5 小时前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端
苏渡苇5 小时前
优雅应对异常,从“try-catch堆砌”到“设计驱动”
java·后端·设计模式·学习方法·责任链模式
long3166 小时前
Aho-Corasick 模式搜索算法
java·数据结构·spring boot·后端·算法·排序算法
rannn_1116 小时前
【苍穹外卖|Day4】套餐页面开发(新增套餐、分页查询、删除套餐、修改套餐、起售停售)
java·spring boot·后端·学习
短剑重铸之日6 小时前
《设计模式》第十一篇:总结
java·后端·设计模式·总结
Dragon Wu7 小时前
Spring Security Oauth2.1 授权码模式实现前后端分离的方案
java·spring boot·后端·spring cloud·springboot·springcloud
一个有梦有戏的人7 小时前
Python3基础:进阶基础,筑牢编程底层能力
后端·python
爬山算法8 小时前
Hibernate(88)如何在负载测试中使用Hibernate?
java·后端·hibernate