`
iakuxgnaw
  • 浏览: 2306 次
社区版块
存档分类
最新评论

ConcurrentLinkedQueue并发原理分析

    博客分类:
  • Java
阅读更多

ConcurrentLinkedQueue是线程安全的队列,它适用于“高并发”的场景

之前知道concurrentHashMap是使用了分段锁的机制来更好的控制细粒度,但是ConcurrentLinkedQueue却是使用了一种非阻塞算法来实现的,在搜索了很久还是不理解的情况下,对着源码苦啃1小时终于有了点眉目。。膜拜Doug Lea大师啊。。

 

首先要先知道ConcurrentLinkedQueue中标识尾节点的tail引用使用的是volatile,每当一个线程的值修改了它都会对其它线程可见。。并且tail节点并不是都是指向的是最后一个尾节点。。后面我们会详细介绍到

 

先上代码

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) {                                                // A
                // p is last node
                if (p.casNext(null, newNode)) {                             //B
                    // 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                  //C
                        casTail(t, newNode);  // Failure is OK.
                    return true;
                }
                // Lost CAS race to another thread; re-read next
            }
            else if (p == q)                                                //D
                // 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                                                           //E
                // Check for tail updates after two hops.
                p = (p != t && t != (t = tail)) ? t : q;
        }
    }

 总体来说 整个offer代码 (添加一个元素到队列尾端)的核心思想就是找到队列的尾节点,然后将新的节点插入到尾节点中。而在并发的情况下对于怎么每次都找到尾节点有点复杂

 

假设有2个线程,线程1和线程2都同时的执行这段加入元素的代码。

假设此时 tail节点指向的就是尾节点。

p指向的是tail,而q则是空

线程1执行到A处,还未执行到B处时;线程2执行到进入了B。那么此时线程1中的p.casNext(null, newNode)便会失败,于是线程1便会退出重新循环加入。这时候就要分看线程1和线程2中的执行情况了。

 

线程2执行完p.casNext(null, newNode)后,执行C,而此时线程2中的p和t是相等的,所以它并没有将新加入的节点修改为尾节点,而是交给了后续的节点来修改。。(其实这么做是为了加快执行效率,这就是很多资料中说的tail节点与尾节点的hop值还在给定的阈值内,所以不修改) 于是线程2就执行完了 退出。

 

线程1刚刚在B处失败了,于是它重新判断,q此时并不是null了,所以它运行到了E出,而E出的代码中,重新将p的引用向前推进,因为可能在这个过程中tail的值会被另一个线程3改变,所以t=tail,赋值。因为tai是个volatile类型的,所以它会重新定义t的指向,但是总体方法就是使P向前推进!!找到尾节点

 

至于什么时候p==q,只有当这个队列是空的时候,刚初始化。所以P和Q都是空,于是还是按照核心思想往前推荐,可能是P的引用指向head节点。。

 

doug lea使用hops变量来控制并减少tail节点的更新频率,并不是每次节点入队后都将 tail节点更新成尾节点,而是当 tail节点和尾节点的距离大于等于常量HOPS的值(默认等于1)时才更新tail节点,tail和尾节点的距离越长使用CAS更新tail节点的次数就会越少,但是距离越长带来的负面效果就是每次入队时定位尾节点的时间就越长,因为循环体需要多循环一次来定位出尾节点,但是这样仍然能提高入队的效率,因为从本质上来看它通过增加对volatile变量的读操作来减少了对volatile变量的写操作,而对volatile变量的写操作开销要远远大于读操作,所以入队效率会有所提升...

 

对照理解的时候最好是画个队列图 比较详细。。。。

小白刚研究 说错了 希望各位大牛轻拍~

 

今天就先分析offer函数,关于poll后面在分析~~

分享到:
评论

相关推荐

    ConcurrentLinkedQueue源码分析.rar

    《并发编程:深入剖析ConcurrentLinkedQueue》 在Java并发编程领域,`ConcurrentLinkedQueue`是一个非常重要的数据结构,它是线程安全的无界队列,基于链接节点实现,性能高效。本篇文章将深入探讨`...

    聊聊并发(6)ConcurrentLinkedQueue的

    【标题】:“聊聊并发(6)ConcurrentLinkedQueue的实现原理分析” 【正文】: 并发编程是现代软件开发中的重要组成部分,特别是在多核处理器和分布式系统中,有效地处理并发能够显著提升系统的性能和响应能力。...

    Java 多线程与并发(15-26)-JUC集合- ConcurrentLinkedQueue详解.pdf

    #### 四、ConcurrentLinkedQueue源码分析 ##### 类的继承关系 ```java public class ConcurrentLinkedQueue&lt;E&gt; extends AbstractQueue implements Queue, java.io.Serializable {} ``` `ConcurrentLinkedQueue`...

    汪文君高并发编程实战视频资源下载.txt

     高并发编程第三阶段11讲 AtomicXXXFieldUpdater源码分析及使用场景分析.mp4  高并发编程第三阶段12讲 sun.misc.Unsafe介绍以及几种Counter方案性能对比.mp4  高并发编程第三阶段13讲 一个JNI程序的编写,通过...

    java并发编程实战.zip

    7. **并发集合**:分析了并发环境下集合类的使用,如ConcurrentHashMap、CopyOnWriteArrayList、ConcurrentLinkedQueue等,它们是如何实现线程安全的。 8. **并发设计模式**:介绍了生产者消费者模式、读写锁模式、...

    汪文君高并发编程实战视频资源全集

     高并发编程第三阶段11讲 AtomicXXXFieldUpdater源码分析及使用场景分析.mp4  高并发编程第三阶段12讲 sun.misc.Unsafe介绍以及几种Counter方案性能对比.mp4  高并发编程第三阶段13讲 一个JNI程序的编写,通过...

    抽象工厂并发程序代码demo

    在编程领域,抽象工厂模式是一种重要的设计模式,它属于创建型模式,主要用于对象族的创建。...通过理解抽象工厂模式和并发队列的原理,我们可以更好地分析和学习这个示例,提高自己的并发编程能力。

    java并发编程艺术

    5. **线程安全的数据结构**:介绍Java中线程安全的集合类,如ConcurrentHashMap、CopyOnWriteArrayList、ConcurrentLinkedQueue等,以及它们在并发编程中的应用。 6. **线程间的通信**:讲解wait()、notify()和...

    JAVA并发编程实践(中文)

    4. **原子类与并发容器**:详细阐述了`AtomicInteger`、`AtomicLong`等原子类的使用,以及`ConcurrentHashMap`、`CopyOnWriteArrayList`、`ConcurrentLinkedQueue`等并发容器的实现原理和使用场景。 5. **线程池**...

    Java concurrency集合之ConcurrentLinkedQueue_动力节点Java学院整理

    【Java并发集合与ConcurrentLinkedQueue详解】 在Java并发编程中,集合类的线程安全性是至关重要的。本文将深入探讨Java并发集合中的ConcurrentLinkedQueue,这是一个无界线程安全队列,特别适合处理高并发场景。 ...

    JAVA并发编程实践.pdf

    9. **并发性能分析与优化**:如何检测并发问题、使用JVM内置的监控工具(如JConsole、VisualVM)进行性能分析,以及如何对并发程序进行调优,也是书中的重要内容。 10. **Java内存模型**:书中可能还会涉及Java内存...

    JAVA并发编程实践JavaConcurrencyinPractice-中文-高清-带书签-完整版(Doug Lea)

    6. **并发集合**:分析了ConcurrentHashMap、CopyOnWriteArrayList、ConcurrentLinkedQueue等并发集合的实现和使用,这些集合在多线程环境下提供了高性能的并发访问。 7. **并发设计模式**:介绍了如双检锁/双重...

    java并发编程 PDF

    书中还可能涉及并发集合,如ConcurrentHashMap、CopyOnWriteArrayList和ConcurrentLinkedQueue等。这些集合类在内部采用了高级并发策略,能够在多线程环境下提供高性能和线程安全的访问。 另外,线程间的通信也是...

    高并发编程实战1,2,3阶段

    - **ConcurrentLinkedQueue/ConcurrentLinkedDeque**:高性能的线程安全队列。 #### 第三阶段:实战案例分析 ##### 1. 系统架构设计原则 - **水平扩展**:通过增加服务器数量来提升整体处理能力。 - **垂直扩展**:...

    并发编程、juc工具包源码分析笔记

    在深入学习 Java 并发编程时,还需要关注线程安全、锁机制(如 synchronized 关键字、ReentrantLock 等)、并发容器(如 ConcurrentHashMap、ConcurrentLinkedQueue 等)、原子变量(AtomicInteger、AtomicReference...

    java并发编程实践 张孝翔 讲义

    3. **并发容器**:Java集合框架提供了专为并发设计的容器,如`ConcurrentHashMap`、`ConcurrentLinkedQueue`等。这些容器在多线程环境下表现优秀,能确保数据一致性。书中会分析这些容器的设计和使用方法。 4. **...

    一个简单的Java并发系统动态测试工具.zip

    这个工具基于Java语言,能够帮助开发者深入理解并发程序的工作原理,发现并修复潜在的线程安全问题,如竞态条件、死锁和活锁等。下面我们将详细探讨Java并发编程的相关知识点,并结合这个测试工具来解析其核心功能。...

    java多线程并发实战和源码

    ArrayList、LinkedList等集合类在并发环境下可能存在安全问题,因此,Java提供了并发安全的容器,如ConcurrentHashMap、CopyOnWriteArrayList和ConcurrentLinkedQueue等。这些容器内部实现了线程安全的算法,能够在...

    java并发重构ppt_转温 少

    【文件名称列表】中的"2007-concurrent-ppt"可能是指2007年创建或更新的一份关于并发的PPT文件,这暗示了资料的年代,但并不影响其核心知识点的时效性,因为Java并发的基本概念和原理依然适用。 在Java并发编程中,...

    java 并发视频教程

    - **`ConcurrentLinkedQueue`**:线程安全的链表队列实现。 - **`BlockingQueue`**:提供了一种阻塞式的队列操作,常用于线程池的工作队列。 - **`CopyOnWriteArrayList`**:线程安全的动态数组实现,适合读多写少的...

Global site tag (gtag.js) - Google Analytics