Java朝花夕拾-非阻塞队列之ConcurrentLinkedQueue

本文深入解析ConcurrentLinkedQueue的内部实现,包括其基于链表的非阻塞队列结构,采用的CAS算法进行线程安全操作,以及入队和出队的具体流程。通过源码分析,帮助读者理解其高效并发特性和应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ConcurrentLinkedQueue 
   非阻塞队列 
   采用先进先出的规则。
   采用链表实现,由头节点和尾节点组成
   当插入元素时,不会加锁,因此不会阻塞,当时会有一个死循环,直到插入成功,遍历链表,找到队尾,将元素插入
   采用cas算法

public boolean offer(E e) {

        if (e == null) throw new NullPointerException();

        //入队前,创建一个入队节点

        Node</e><e> n = new Node</e><e>(e);

        retry:

        //死循环,入队不成功反复入队。

        for (;;) {

            //创建一个指向tail节点的引用

            Node</e><e> t = tail;

            //p用来表示队列的尾节点,默认情况下等于tail节点。

            Node</e><e> p = t;

            for (int hops = 0; ; hops++) {

            //获得p节点的下一个节点。

                Node</e><e> next = succ(p);

     //next节点不为空,说明p不是尾节点,需要更新p后在将它指向next节点

                if (next != null) {

                   //循环了两次及其以上,并且当前节点还是不等于尾节点

                    if (hops > HOPS && t != tail)

                        continue retry;

                    p = next;

                }

                //如果p是尾节点,则设置p节点的next节点为入队节点。

                else if (p.casNext(null, n)) {

                  //如果tail节点有大于等于1个next节点,则将入队节点设置成tair节点,更新失败了也没关系,因为失败了表示有其他线程成功更新了tair节点。

if (hops >= HOPS)

                        casTail(t, n); // 更新tail节点,允许失败

                    return true;

                }

               // p有next节点,表示p的next节点是尾节点,则重新设置p节点

                else {

                    p = succ(p);

                }

            }

        }

    }

  出队列时:

  

public E poll() {

           Node</e><e> h = head;

       // p表示头节点,需要出队的节点

           Node</e><e> p = h;

           for (int hops = 0;; hops++) {

                // 获取p节点的元素

                E item = p.getItem();

                // 如果p节点的元素不为空,使用CAS设置p节点引用的元素为null,如果成功则返回p节点的元素。

                if (item != null && p.casItem(item, null)) {

                     if (hops >= HOPS) {

                          //将p节点下一个节点设置成head节点

                          Node</e><e> q = p.getNext();

                          updateHead(h, (q != null) ? q : p);

                     }

                     return item;

                }

                // 如果头节点的元素为空或头节点发生了变化,这说明头节点已经被另外一个线程修改了。那么获取p节点的下一个节点

                Node</e><e> next = succ(p);

                // 如果p的下一个节点也为空,说明这个队列已经空了

                if (next == null) {

              // 更新头节点。

                     updateHead(h, p);

                     break;

                }

                // 如果下一个元素不为空,则将头节点的下一个节点设置成头节点

                p = next;

           }

           return null;

     }

  

转载于:https://www.cnblogs.com/dengyuanqi/p/6306820.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值