码迷,mamicode.com
首页 > 其他好文 > 详细

【JUC源码解析】ConcurrentLinkedQueue

时间:2018-02-25 17:27:15      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:.com   ransient   ati   log   大于等于   bubuko   头结点   源码解析   成功   

简介

ConcurrentLinkedQueue是一个基于链表结点的无界线程安全队列。

概述

队列顺序,为FIFO(first-in-first-out);队首元素,是当前排队时间最长的;队尾元素,当前排队时间最短的。新元素,从队尾插入;检索元素,从队首开始,Node的next属性保证从队首能遍历到所有的有效元素。由于此队列使用Node的next属性联接在一起,因此不允许有null元素。

队列的实现具有非阻塞,弱一致性,滞后更新等特点。

队列维护两个指针,head指针和tail指针,一开始,head和tail都指向“哑巴”结点(Node的item属性为空),新结点从尾部插入,队列向后增长,然而,tail并不总是指向尾部(队列中最后一个元素),head也并不总是指向头部(队列中第一个有效元素)。

head和tail的更新是独立的,也就是说,tail指针很可能比head指针指向更靠前的结点(当然,此结点是已删除结点,下次更新tail结点后,又跑到head结点后面或同一个),这保证了插入和删除的独立性。

hop,跳,指的是head或tail结点与第一个或最后一个结点的距离,大于等于2时更新。

新元素入队时,最后一个结点的next域为null,队列中的所有未删除结点的item域不能为null且从head都可以在O(N)时间内遍历到;对于要删除的结点,不是将其引用直接置为null,而是将其item域先置为null(迭代器在遍历时会跳过item为null的结点);允许head和tail滞后更新,即前文提到的head/tail指针并非总是指向队列的头/尾节点。

head结点(head指针指向的结点)的next域不能指向该结点自身,tail结点的next域可以指向该结点自己。

源码解析

Node

1         volatile E item; // 元素内容
2         volatile Node<E> next; // 指向下一个结点

头结点和尾结点

1     private transient volatile Node<E> head; // 头结点
2     private transient volatile Node<E> tail; // 尾结点

 入队

 1     public boolean offer(E e) {
 2         checkNotNull(e); // 为空,抛出异常
 3         final Node<E> newNode = new Node<E>(e);
 4 
 5         for (Node<E> t = tail, p = t;;) { // t作为tail的快照,p指向t结点
 6             Node<E> q = p.next; // q是p的next结点
 7             if (q == null) { // q为null,说明p是最后一个结点,可以直接插入
 8                 if (p.casNext(null, newNode)) { // 设置新结点为p的next结点
 9                     if (p != t) // 两跳,更新tail结点
10                         casTail(t, newNode); // 失败,表示其他线程更新成功了
11                     return true; // 返回
12                 }
13             } else if (p == q) // p结点的next域指向了它自己,此操作在更新head结点时发生,表明此结点及其之前的结点已被删除
14                 p = (t != (t = tail)) ? t : head; // 如果tail结点已被其他线程更新,则p指向t(tail)结点,否则(tail指针指向已被删除的结点),p指向head结点,跳到头部,指向活着的结点
15             else
16                 p = (p != t && t != (t = tail)) ? t : q; // p指向它的next结点(q),并在2跳时检查tail结点是否更新,如果更新,则指向tail结点
17         }
18     }

 初始队列

 技术分享图片

 

【JUC源码解析】ConcurrentLinkedQueue

标签:.com   ransient   ati   log   大于等于   bubuko   头结点   源码解析   成功   

原文地址:https://www.cnblogs.com/aniao/p/aniao_clq.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!