ConcurrentLinkedQueue 线程安全的 队列分析 CAS 步骤分析:
public boolean offer(E e) {
if (e == null) throw new NullPointerException();
Node<E> n = new Node<E>(e, null);
for (;;) {
// 获得列表的 尾节点
Node<E> t = tail;
// 获得列表的 尾节点 的下一个节点
Node<E> s = t.getNext();
if (t == tail) { //------------------------------a
if (s == null) { //------------------------------b
if (t.casNext(s, n)) { //------------------------------c
casTail(t, n); //------------------------------d
return true;
}
} else {
casTail(t, s); //------------------------------e
}
}
}
}
/**
【步骤a】:t==tail是最上层的协调,如果其他线程改变了tail的引用,则说明现在获得不是最新的尾指针需要重新循环获得最新的值。
【步骤b】:s==null的判断。【【【静止状态下tail的next一定是指向null的】】】,但是 多线程下的另一个状态就是中间态:tail的指向没有改变,但是其next已经指向新的结点,即完成tail引用改变前的状态,这时候s!=null。这里就是协调的典型应用,直接进入代码e去协调参与中间态的线程去完成最后的更新,然后重新循环获得新的tail开始自己的新一次的入队尝试。另外值得注意的是a,b之间,其他的线程可能会改变tail的指向,使得协调的操作失败。
从这个步骤可以看到无锁实现的复杂性。
【步骤c】:t.casNext(s, n)是入队的第一步,因为入队需要两步:更新Node的next,改变tail的指向。代码c之前可能发生tail引用指向的改变或者进入更新的中间态,这两种情况均会使得t指向的元素的next属性被原子的改变,不再指向null。这时代码c操作失败,重新进入循环。
【步骤d】:这是完成更新的最后一步了,就是更新tail的指向,最有意思的协调在这儿又有了体现。从代码看casTail(t, n)不管是否成功都会接着返回true标志着更新的成功。首先如果成功则表明本线程完成了两步的更新,返回true是理所当然的;如果 casTail(t, n)不成功呢? 要清楚的是完成代码c则代表着更新进入了中间态,代码d不成功则是tail的指向被其他线程改变。意味着对于其他的线程而言:它们得到的是中间态的更新,s!=null,进入代码e帮助本线程执行最后一步并且先于本线程成功。这样本线程虽然代码d失败了,但是是由于别的线程的协助先完成了,所以返回true也就理所当然了。
*/
以上都是摘自博客:http://yanxuxin.iteye.com/blog/586943
看了2、3遍实在是理解不了。
最后看到并发编程实战这本书,P272--P274 他解释的很好很好,主要是它这个变量名起的好,一个好的变量名是多么的重要。
理解完成之后再回来看上面那片博客解释的也不错。
================================以下为个人原创理解部分=========================
先普及几个知识点:
对于一个链表:在稳定状态 也就是没有线程对他进行任何操作的时候,
1、head指向 首节点
2、tail指向 尾节点
3、tail节点的next是指向nul的。 【这个非常重要需要记下了,稳定状态的list它的tail节点的next节点指向null。 tail.getNext() == null表示此链表处于稳点状态 】
链表的入队操作包括两步:
第一步:把当前链表的最后一个元素的 next节点连接到新插入的节点。(本来这个节点是指向null的)
第二步:更新整个链表 tail节点指向刚插入节点。
我翻译一遍我对上面程序的理解:
【步骤a】:判断刚刚获取到的tail是否有变化,如果有变化重新获取,如果没变化继续往下。因为是多线程操作,即便是上一步刚刚赋值:Node<E> t = tail; 在进行判断t == tail也不一定是一样的。
【步骤b】:接着上一步,tail节点还没有变化,继续判断链表是否处于稳定状态就是刚才第三点普及的知识。tail.getNext() == null。 如果成立表示,此链表处于稳定状态我可以开始对他进行 入队列操作。进入步骤c 如果不成立,就表示有线程入队完成了第一步,还没有来得及完成第二步。不成立跳转到步骤e
【步骤c】:t.casNext(s, n)是入队的第一步。第一步成功,继续下一步更新tail指向新插入的节点。 第一步失败,重新进入循环开始新一轮CAS操作。
【步骤d】:入队列第一步成功,执行第二步。casTail(t, n);把tail节点指向new节点。这一步有一个特别需要注意的是,不管这一步是否成功。都会返回ture,这不科学啊???骚年无躁,请看步骤b跳转到的步骤e完成了 casTail(t, n); 这一步。
【步骤e】:casTail(t, s); 更新tail节点到tail.getNext()节点也就是new节点,因为能进入步骤e就说明队列处于不稳定状态。 步骤d 和步骤e 效果其实是一样的。步骤d是无并发情况下正常执行,步骤e是多线程下 第一个线程完成了入队的第一步,第二个线程来完成了入队的第二步。
解释的有点啰嗦……
看不懂的还是多看几遍http://hellosure.iteye.com/blog/1126541 这个博客 主要是那几个图。
或者看并发编程实践 这本书。
对同一个知识点 多几个方面去看,说不定啥时候一下子就通了……
- 大小: 79 KB
分享到:
相关推荐
《并发编程:深入剖析ConcurrentLinkedQueue》 在Java并发编程领域,`ConcurrentLinkedQueue`是一个非常重要的数据结构,它是线程安全的无界队列,基于链接节点...理解和掌握其工作原理对于提升并发编程能力至关重要。
总的来说,选择LinkedBlockingQueue还是ConcurrentLinkedQueue,主要取决于你的并发模型、对性能的需求以及是否需要队列的边界控制。如果你需要保证线程间的顺序,或者对系统内存有限制,LinkedBlockingQueue可能是...
ConcurrentLinkedQueue
### 并发队列 ConcurrentLinkedQueue 和阻塞队列 LinkedBlockingQueue 用法详解 #### 一、并发队列 ConcurrentLinkedQueue 概述 `ConcurrentLinkedQueue` 是 Java 并发包 `java.util.concurrent` 提供的一个高性能...
本文将详细介绍如何使用Java中的`ConcurrentLinkedQueue`数据结构,结合Spring Boot的特性,实现异步处理浏览器发送的请求。 首先,`ConcurrentLinkedQueue`是Java并发包`java.util.concurrent`中的一个无界线程...
【标题】:“聊聊并发(6)ConcurrentLinkedQueue的实现原理分析” 【正文】: 并发编程是现代软件开发中的重要组成部分,特别是在多核处理器和...理解并掌握其工作原理对于优化并发代码、提升系统性能具有重要意义。
ConcurrentLinkedQueue 在考虑并发的时候可以先考虑单线程的情况,然后再将并发的情况考虑进来。 比如ConcurrentLinkedQueue: 1、先考虑单线的offer 2、再考虑多线程时候的offer: · 多个线程offer...
### Java多线程与并发(15-26)-JUC集合-ConcurrentLinkedQueue详解 #### 一、ConcurrentLinkedQueue概述 `ConcurrentLinkedQueue`是Java实用工具...通过对其实现原理的深入理解,可以更好地应用这一组件解决实际问题。
【Java并发集合与ConcurrentLinkedQueue详解】 在Java并发编程中,集合类的线程安全性是至关重要的。本文将深入探讨Java并发集合中的ConcurrentLinkedQueue,这是一个无界线程安全队列,特别适合处理高并发场景。 ...
15.并发容器之ConcurrentLinkedQueue 16.并发容器之CopyOnWriteArrayList 17.并发容器之ThreadLocal 18.一篇文章,从源码深入详解ThreadLocal内存泄漏问题 19.并发容器之BlockingQueue 20.并发容器之...
在准备Java面试时,这本书能帮助你系统地复习和深化对Java语言的理解,提升你的技术实力和面试竞争力。 一、Java基础 1. 数据类型:深入理解基本数据类型(整型、浮点型、字符型、布尔型)及其用法,掌握自动装箱...
2. **并发容器**:如ConcurrentHashMap、CopyOnWriteArrayList、ConcurrentLinkedQueue等,它们为并发操作提供了线程安全的解决方案。 3. **线程池**:ExecutorService和ThreadPoolExecutor的理解,如何配置线程池...
2. **集合框架**:深入理解List、Set、Queue等接口以及它们的实现类,如ArrayList、LinkedList、HashSet、HashMap等,特别是对于并发安全的集合(ConcurrentHashMap、ConcurrentLinkedQueue等)的理解和使用。...
这里,我们将深入探讨Java编程语言的核心概念、高级特性以及在实际开发中的应用,以帮助你准备类似的面试。 一、Java基础 1. 类与对象:理解面向对象编程的基本原则,如封装、继承和多态。掌握类的创建、对象实例化...
- **ConcurrentLinkedQueue**:基于链表的无界队列。 **线程局部变量:** - **ThreadLocal类**:为每个线程提供独立的变量副本,避免线程间的数据共享。 - **应用场景**:如数据库连接管理、HTTP会话管理等。 --- ...
3. **ConcurrentLinkedQueue**: 提供了一个基于链表的无界队列实现,适用于高并发场景。 #### 五、线程协作 线程之间的协作是多线程编程中的另一个关键方面,涉及到线程之间的通信和同步。Java提供了多种机制来...
为了帮助你更好地理解和准备Java相关的面试与笔试,以下是一些可能涵盖的重要知识点: 1. **基础语法**:Java的基础语法包括数据类型(如基本类型与引用类型)、变量、运算符、流程控制(if语句,switch,for,...
- 并发容器:ConcurrentHashMap、CopyOnWriteArrayList、ConcurrentLinkedQueue等的应用场景和特性。 6. **设计模式** - 工厂模式:理解简单工厂、工厂方法、抽象工厂模式。 - 单例模式:了解懒汉式、饿汉式、...
2. **并发容器**:理解ConcurrentHashMap、ConcurrentLinkedQueue等并发安全容器。 3. **线程池**:掌握ThreadPoolExecutor的工作原理,合理配置线程池参数。 五、网络编程 1. **Socket编程**:了解TCP/IP协议,...
本文将深入探讨`ConcurrentLinkedQueue`、`ArrayBlockingQueue`以及`LinkedBlockingQueue`这三种实现,并分析它们的设计原理与应用场景。 首先,我们来看`ConcurrentLinkedQueue`。它是基于非阻塞算法(CAS,...