前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java并发-21.ConcurrentLinkedQueue

Java并发-21.ConcurrentLinkedQueue

作者头像
悠扬前奏
发布2019-06-01 14:08:16
3120
发布2019-06-01 14:08:16
举报
文章被收录于专栏:悠扬前奏的博客
  • ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列。
  • 采用FIFO对节点排序
  • 采用CAS实现非阻塞

1. ConcurrentLinkedQueue结构

  • 由head和tail节点组成
  • 每个节点(Node)由节点元素(item)和指向下一个节点的指针(next)组成

2. 入列

  • 入列就是将入列节点添加到队列尾部
  • 入列源码:
代码语言:javascript
复制
    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;
        }
    }
  • 获取p节点的下一个节点
代码语言:javascript
复制
    final Node<E> succ(Node<E> p) {
        Node<E> next = p.next;
        return (p == next) ? head : next;
    }
  • 设置入队节点为尾节点 casNext(null, n)可以将入队节点置为尾节点的next节点,p为null就表示p是队列尾节点了,如果不为空,说明其他线程更新了尾节点,需要重新获取

3. 出列

获取头节点的元素,然后判断头结点是否为空,为空说明其他线程已经获取了该节点,如果不为空,CAS将头结点设置为null,成功返回头结点,不成功重新获取。

代码语言:javascript
复制
    public E poll() {
        restartFromHead:
        for (;;) {
            for (Node<E> h = head, p = h, q;;) {
                E item = p.item;

                if (item != null && p.casItem(item, null)) {
                    // Successful CAS is the linearization point
                    // for item to be removed from this queue.
                    if (p != h) // hop two nodes at a time
                        updateHead(h, ((q = p.next) != null) ? q : p);
                    return item;
                }
                else if ((q = p.next) == null) {
                    updateHead(h, p);
                    return null;
                }
                else if (p == q)
                    continue restartFromHead;
                else
                    p = q;
            }
        }
    }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019.05.31 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. ConcurrentLinkedQueue结构
  • 2. 入列
  • 3. 出列
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档