首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Java并发编程(七)ConcurrentLinkedQueue的实现原理和源码分析

使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现,而非阻塞的实现方式则可以使用循环CAS的方式来实现,本节我们就来研究下ConcurrentLinkedQueue...从第一个if判断就来判定p有没有next节点如果没有则p是尾节点则将入队节点设置为p的next节点,同时如果tail节点不是尾节点则将入队节点设置为tail节点。...3.出队列 出队列的就是从队列里返回一个节点元素,并清空该节点对元素的引用。让我们通过每个节点出队的快照来观察下head节点的变化。 ?...首先获取head节点的元素,并判断head节点元素是否为空,如果为空,表示另外一个线程已经进行了一次出队操作将该节点的元素取走,如果不为空,则使用CAS的方式将head节点的引用设置成null,如果CAS...4.队列判空 有些人在判断队列是否为空时喜欢用queue.size()==0,让我们来看看size方法: ?

1K100

数据结构 | 栈和队列

队列(Queue)也是一种特殊的线性表,特殊之处在于它只允许在表的前端(Front)进行删除操作,而在表的后端(Rear)进行插入操作,和栈一样,队列 的部分操作也会受到限制。...ps) //查看栈的有效元素个数 { assert(ps); //栈的大小就是当前栈的有效元素个数 return ps->top; } 判断栈是否为空 判断栈是否为空,太简单了,一行代码解决...QueueEmpty(pq)); return pq->front->data; } 查看队尾 同样需要判断队列是否为空 不为空才能查看,队尾元素为 队尾指针 的指向值 QListDataType...QueueEmpty(pq)); return pq->rear->data; } 查看队内有效元素 队列中的有效元素数,就是之前一直默默工作的 队列长度 size,直接返回它的值就好了,没什么技巧...此时判断队列是否为空,有多种方法 通过 size 判断,为0,说明队列为空 通过 队头指针 或 队尾指针 判断,为空说明队空 这里使用第二种方法,通过 队头指针 进行判断 当然,返回值是 布尔值 ,

19320
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    数据结构从入门到精通——队列

    队列 前言 队列是一种特殊的线性数据结构,遵循先入先出(FIFO)的原则。它只允许在队列的末尾添加元素(称为入队操作),并从队列的开头移除元素(称为出队操作)。...A 、从队尾插入一个新元素 B、 从队列中删除第i个元素 C、 判断一个队列是否为空 D、 读取队头元素的值 现有一循环队列,其队头指针为front,队尾指针为rear;循环队列长度为N。...在出队列操作中,队列头部元素被移除并返回,队列中的其他元素则向前移动一位。出队列操作的时间复杂度通常为O(1),因为它只涉及到对队列头部元素的移除和返回,不需要遍历整个队列。...队列具有先进先出(FIFO)的特性。 "返回队头元素"是对队列进行的一种操作,即获取队列前端(队头)的元素,但并不从队列中删除该元素。这通常用于查看队列中的第一个元素,但不改变队列的状态。...如果头部和尾部指针或索引相同,说明队列为空;否则,队列不为空。此外,也可以使用队列提供的相关函数或方法,如isEmpty()等,来检测队列是否为空。

    38010

    JDK容器学习之Queue:LinkedBlockingQueue

    (); /** * 队列头,但其中没有有效数据,它的下一个才保存实际的数据 * Head of linked list...; } } 说明 底层结构为单向链表,其中队列头不包含有效数据; 队列长度有界,为初始化时指定的容量大小;没指定时,默认为int最大值 count实时表示队列中元素的个数,采用原子进行+/-1 进队和出队是两个锁...出队锁 判断队列是否非空,为空时阻塞出队线程 其他线程入队成功,唤醒因队列为空被阻塞的线程 若出队之前,队列为满的,则唤醒因为队列满无法入队而阻塞的线程 ---- 查看上面的源码时,还发现一个非常有意思的地方...假设一种场景,一个空队列,两个线程(A,B)都执行出队,被阻塞; 此时线程C执行入队,入队完成,因为队列由空到非空,会唤醒一个被阻塞的出队线程(假设为A); 因为出队和入队是可以并发的,现在在线程A执行...其他方法 除了出队和入队的方法之外,还有几个有意思的方法,如队列中元素以数组形式输出,判断队列是否有元素,这两个操作,都会竞争出队和入队锁,确保在执行这个方法时,队列不会被其他线程修改 public boolean

    75360

    走进C#并发队列ConcurrentQueue的内部世界

    ,它创建了一个长度为32的数组,并创建了与之对应的状态数组,然后初始化了位置指针(m_low=0,m_high=-1,此时表示一个空的Segment)。...而且从代码注释中可以看到,这里不会出现线程竞争的情况,因为其他线程都因为位置不够被阻塞都在自旋等待中。...关于如何判断队列是否为空总结就一句话:当首段m_head不包含任何数据且没有下一段的时候队列才为空,详细的判断过程源码注释中写的很清楚,限于篇幅不详细介绍。...的值是否相等 如果相等则m_low=lowLocal+1,如果不相等就什么都不做,不管是否相等,始终返回m_low的原始值 整个操作是原子性的,对CPU而言就是一条指令,这样就可以保证当前位置只有一个线程执行出队操作...还有一个TryPeek()方法和出队类似,它是从队首获取一个元素但是无需移除该元素,可以看做Dequeue的简化版,不再详细介绍。

    2.3K20

    Python 算法基础篇:栈和队列的实现与应用

    栈可以看作是一种只允许在一端进行插入和删除操作的线性表。...类中的方法包括:判断栈是否为空 is_empty ,入栈 push ,出栈 pop ,查看栈顶元素 peek ,以及获取栈的大小 size 。...最后检查栈是否为空,若为空则说明所有括号都正确配对。 2.2.2 逆波兰表达式求值 逆波兰表达式(后缀表达式)是一种不需要括号来表示运算优先级的数学表达式。栈可以用于求解逆波兰表达式的值。...类中的方法包括:判断队列是否为空 is_empty ,入队 enqueue ,出队 dequeue ,查看队头元素 peek ,以及获取队列的大小 size 。...类中的方法包括:判断循环队列是否为空 is_empty ,判断循环队列是否为满 is_full ,入队 enqueue ,出队 dequeue ,查看队头元素 peek ,以及获取循环队列的大小 size

    47120

    【算法与数据结构】队列的实现详解

    出队(Dequeue):通过头指针删除队列头部元素,即从队列中移除元素。 空队列:当头指针和尾指针相同时,表示队列为空。 满队列:当尾指针指向队列容量最大位置时,表示队列已满。...(Queue* pq); //获取队列中有效元素个数 QDataType SizeQueue(Queue* pq); //队列是否为空 QDataType IsEmpty(Queue* pq); //...两种常见的方法: 循环队列: 循环队列是一种特殊的顺序队列,通过将队列的数组视为一个循环的环形结构,使得在队列尾部插入元素时可以利用数组头部的空闲空间,从而解决了假溢出的问题。...,front从0开始可以实现队列元素的循环利用。...// 查看队列是否为空 int isEmpty(Cir_Queue* queue) { return (queue->size == 0); } 查看队列是否已满 // 查看队列是否已满 int

    24810

    10分钟从实现和使用场景聊聊并发包下的阻塞队列

    );  } 从字段中,我们可以知道它使用单向链表的节点、且用首尾节点记录队列的头尾,并且它使用两把锁、两个等待队列作用于队头、尾,与ArrayBlockingQueue相比能够增加并发性能 有个奇怪的地方...这是由于两把锁,作用于入队与出队的操作,入队与出队也可能并发执行,同时修改count,因此要使用原子类保证修改数量的原子性 在初始化时需要设置容量大小,否则会设置成无界的阻塞队列(容量是int的最大值)...首尾节点会指向一个值为空的虚拟节点 后续首节点会一直指向值为空的虚拟节点 而真实的队头节点实际上是这个虚拟节点的next节点 来看看入队操作   public boolean offer(E e,...比如多线程处理多个阻塞队列的任务(一一对应),每个线程从队头获取任务处理,当A线程处理完它负责的阻塞队列所有任务时,它再从队尾窃取其他阻塞队列的任务,这样就不会发生竞争,除非队列中只剩一个任务,才会发生竞争...:DelayQueue存放缓存有效期,当可以获取到元素时,说明缓存过期 定时任务调度: 将定时任务的时间设置为延时时间,一旦可以获取到任务就开始执行 以定时线程池ScheduledThreadPoolExecutor

    33521

    邂逅数组与队列

    问题 可以看到二维数组中很多数据都是默认值0, 因此可以采用稀疏数组的方式存储数据 稀疏数组( SparseArray ) 当一个数组大部分数据元素为0 or 同一个值时, 采取稀疏数组 稀疏数组的处理方法...队列与队列模拟 下面我们来学习线性结构的一种数据结构: 队列 队列是一个有序表, 编程上可以通过数组和链表来实现 遵循先入先出原则....且在构造函数中front=rear=-1, 队列用一个数组模拟, 队列长=maxSize 执行入队, 需要判断是否队满; 指定出队和查询需要判断是否队空; 队空条件 rear==front, 队满条件...三个元素都入队后, 查看入队情况 ? 一次取出数据元素 在这里的演示中可以看到, 先入队的元素先出队,直至队空 ?...->添加元素至队满->查看元素->取出所有元素至队空->查看是否能够重新加入该元素->查看这些元素 ?

    55910

    回归Java基础:LinkedBlockingQueue阻塞队列解析

    LinkedBlockingQueue 容量是一个原子变量count,它的初始值为0。...释放完锁后,判断容量是否为空,如果是,唤醒notEmpty的阻塞线程。 put操作 put方法也是向队列尾部插入一个元素。如果元素为null,抛出空指针异常。...poll操作 从队列头部获取并移除一个元素, 如果队列为空则返回 null, 该方法是不阻塞的。...返回出队元素x remove操作 删除队列里面指定的元素,有则删除并返回 true,没有则返回 false。...它有头尾两个节点,入队操作是从尾节点添加元素,出队操作是对头节点进行操作。 它的容量是原子变量count,保证szie获取的准确性。 它有两把独占锁,保证了队列操作原子性。

    43910

    【Python数据结构系列】☀️《队列(顺序队列、链式队列、双端队列)》——知识点讲解+代码实现☀️

    拿图 1 中的队列来说,从数据在队列中的存储状态可以分析出,元素 1 最先进队,其次是元素 2,最后是元素 3。...代码实现:队列的顺序表示和实现(难度:★) 实现基本功能:(包括但不限于,可以根据自己能力继续扩展) (1)初始化队列 (2)判断队列是否为空 (3)返回队头元素 (4)返回队列的长度 (5)入队 :...3.3 链式队列数据出队 当链式队列中,有数据元素需要出队时,按照 “先进先出” 的原则,只需将存储该数据的节点以及它之前入队的元素节点按照原则依次出队即可。...4.2 双端队列的原型 对于双端队列的原型,可以还用排队的例子来说明,这里主要以此说明从队头入队和从队尾出队的例子: (1)如果一个排在队头的顾客进了餐厅却发现暂无空桌,则其再次回到队头的行为就相当于从队头入队操作...队列的应用 应用1:回文词检验 回文词检查是数据结构中的常见任务,这一任务可以应用双端队列直观有效地完成。将待检查的字符串按顺序载入队列,首尾两侧弹出并比较,出现不一致时则判断为不是回文数。

    1K20

    栈和队列

    从栈的定义可以看出,栈只支持两个基本操作:入栈 push() 和 出栈 pop() ,也就是在栈顶插入一个数据和从栈顶删除一个数据。...# 栈的应用场景 (1)函数调用栈 (2)表达式求值 (3)表达式匹配 可以借助栈来检查表达式中的括号是否匹配 # 队列 在 FIFO 数据结构中,将首先处理添加到队列中的第一个元素。...队列的最基本操作:入队 enqueue() ,放一个数据到队列尾部;出队 dequeue() ,从队列头部取一个元素。 队列可以用数组来实现,也可以用链表来实现。...循环队列的要点是确定好 队空和队满的判定条件。 在用数组实现的非循环队列中,队满的判断条件是 (tail+1) % n == head ,队空的判断条件是 head == tail 。...简单来说,就是: 在队列为空的时候,从队头取数据会被阻塞。

    28910

    12张图一次性搞懂高性能并发容器ConcurrentLinkedQueue

    、6个代码案例、5个原理图让你彻底搞懂Synchronized 的第二小节 如果不理解volatile可以查看这篇文章5个案例和流程图让你从0到1搞懂volatile关键字 数据结构 ConcurrentLinkedQueue...从名称上来看就能够知道,它支持并发、由链表实现的队列 通过源码,我们可以看到**ConcurrentLinkedQueue使用字段记录首尾节点、并且节点的实现是单向链表** 并且这些关键字段都被volatile...q 用于记录p的后继节点 出队的情况分为四种 当p为真正头节点时,CAS将数据设置为空,然后判断head是否为真正头节点,不是则更新头节点,然后将原来的头节点next指向它自己构建成哨兵节点 当p的后继节点为空时...h1、h2、h3四个节点 在第一次出队时,由于head指向的哨兵节点数据域为空,会来到第四种情况,即将p改为它的后继节点,继续向后遍历 在第二次循环时,p为h1节点,由于数据不为空,CAS将数据设置为空...在第二次出队时,满足第一种情况,直接CAS将h2节点数据设置为空,不会更新头节点 在第三次出队时,也类似与第一次出队,满足第四种情况 在第二次循环时,去CAS将数据设置为空,更新头节点,将原来的头节点设置成哨兵节点

    20121

    Java中的栈和队列

    方法 功能 Stack() 构造一个空的栈 E push (E e) 将e入栈,并返回e E pop() 将栈顶元素出栈并返回 E peak() 获取栈顶元素 int size() 获取栈中有效元素个数...括号匹配:在文本编辑器或编程语言解析器中,栈可以用来检查括号是否正确匹配。遇到开括号时将其推入栈中,遇到闭括号时尝试从栈中弹出一个开括号并检查是否匹配。...综上所述,栈是一种通用的数据结构,用于维护数据的先进后出顺序;虚拟机栈是JVM内部为每个线程分配的一个特定区域,用于管理方法调用过程中的数据;而栈帧则是虚拟机栈中用于记录单个方法调用信息的数据块。...() 检测队列是否为空 3.2队列的模拟实现 队列中既然可以存储元素,那底层肯定要有能够保存元素的空间,那么会选择顺序结构还是链式结构呢?...,那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。

    39810

    『互联网架构』软件架构-分布式系列并发编程atomic&collections(31)

    这个包里面提供了一组原子变量的操作类,这些类可以保证在多线程环境下,当某个线程在执行atomic的方法时,不会被其他线程打断,而别的线程就像自旋锁一样,一直等到该方法执行完成,才由JVM从等待队列中选择一个线程执行...这个指令会对内存中的共享数据做原子的读写操作。在Java并发应用中通常指CompareAndSwap或CompareAndSet,即比较并交换,是实现并发算法时常用到的一种技术。...B,当且仅当预期值A和内存值V相同时,将内存值修改为B并返回true,否则什么都不做,并返回false 3.CAS优缺点 系统在硬件层面保证了CAS操作的原子性,不会锁住当前线程,它的效率是很高的。...JDK提供了AtomicReference类来保证引用对象的原子性,可以把多个变量放在一个对象里来进行CAS操作 ABA CAS在操作值的时候检查值是否已经变化,没有变化的情况下才会进行更新。...当入队时队列已满,或出队时队列已空,不同函数的效果。

    37130

    『互联网架构』软件架构-分布式系列并发编程atomic&collections(31)

    这个包里面提供了一组原子变量的操作类,这些类可以保证在多线程环境下,当某个线程在执行atomic的方法时,不会被其他线程打断,而别的线程就像自旋锁一样,一直等到该方法执行完成,才由JVM从等待队列中选择一个线程执行...这个指令会对内存中的共享数据做原子的读写操作。在Java并发应用中通常指CompareAndSwap或CompareAndSet,即比较并交换,是实现并发算法时常用到的一种技术。...B,当且仅当预期值A和内存值V相同时,将内存值修改为B并返回true,否则什么都不做,并返回false 3.CAS优缺点 系统在硬件层面保证了CAS操作的原子性,不会锁住当前线程,它的效率是很高的。...JDK提供了AtomicReference类来保证引用对象的原子性,可以把多个变量放在一个对象里来进行CAS操作 ABA CAS在操作值的时候检查值是否已经变化,没有变化的情况下才会进行更新。...当入队时队列已满,或出队时队列已空,不同函数的效果。

    48120

    数据结构与算法 --- 组数、链表、栈和队列(二)

    定义 栈:「栈是一种受限的线性表,它的原则是后进先出,后进先出,也称为 LIFO(Last In First Out)或 FILO(First In Last Out),它只允许再一端进行插入和删除操作...定义 队列:「队列也是一种受限制的线性表,它的原则是先进先出 FIFO(First In First Out),从队首取数据的操作称为“出队”,数据放入到队尾的操作称之为“入队”。」...例:有一个顺序队列,当a、b、c、d依次入队后,队列中的「head」指针指向下标为0的位置,tail指针指向下标为4的位置,当a、b出队,队列中的「head」指针指向下标为2的位置,tail指针仍然指向下标为...通过这样的方法,就成功避免了在「tail」=n时的数据移动操作,还需注意的一点时队列空和队列满的判断 当队列空时,「head」=「tail」。...原子操作,可以实现非常高效的无锁并发队列。

    25820

    死磕 java集合之ConcurrentLinkedQueue源码分析

    t : q; }} 入队整个流程还是比较清晰的,这里有个前提是出队时会把出队的那个节点的next设置为节点本身。...// 如果p的next为空,说明队列中没有元素了 // 更新h为p,也就是空元素的节点 updateHead(h, p);...p = q; } }}// 更新头节点的方法final void updateHead(Node h, Node p) { // 原子更新h为p成功后,延迟更新h的...next为它自己 // 这里用延迟更新是安全的,因为head节点已经变了 // 只要入队出队的时候检查head有没有变化就行了,跟它的next关系不大 if (h !...(1)两者都是线程安全的队列; (2)两者都可以实现取元素时队列为空直接返回null,后者的poll()方法可以实现此功能; (3)前者全程无锁,后者全部都是使用重入锁控制的; (4)前者效率较高,后者效率较低

    39420

    【数据结构与算法】使用单链表实现队列:原理、步骤与应用

    一、引言 队列的概念 队列(Queue)是一种特殊类型的线性数据结构,它遵循特定的操作顺序。...队头(Front):队列中第一个被添加的元素位于队头,但它不是永远位于队列的第一个位置,而是指按照入队顺序,最先应该被出队的元素的位置。在出队操作中,总是从队头移除元素。...队列提供了一种有效的方式来管理和处理需要按照特定顺序执行的任务或数据项。通过使用队列,可以确保数据项按照它们被接收或生成的顺序进行处理,这是许多应用中非常关键的要求。...高效操作: 在单链表队列中,入队(enqueue)操作通常只需要在链表尾部添加一个节点,时间复杂度为O(1)。出队(dequeue)操作也只需要删除链表头部的节点,时间复杂度同样为O(1)。...无论是在操作系统、网络通信、打印机任务处理、事件驱动编程还是游戏开发中,我们都可以看到单链表队列的身影。因此,掌握单链表队列的实现原理和应用方法对于程序员来说是非常有必要的。

    13500

    用Rust实现数据结构和算法:从链表到哈希表

    栈可以基于数组或链表实现,这里我们将使用链表实现栈。目标操作:推入(Push):将元素压入栈顶。弹出(Pop):从栈顶删除并返回元素。查看栈顶(Peek):返回栈顶元素,但不删除它。...检查栈是否为空:判断栈是否为空。栈的核心特性是LIFO,因此推入和弹出操作应当具有常数时间复杂度O(1)。我们将通过链表来实现栈,以利用链表在插入和删除操作上的高效性。...目标操作:入队(Enqueue):将元素添加到队列的尾部。出队(Dequeue):从队列的头部删除并返回元素。查看队头(Peek):返回队列的头部元素,但不删除它。检查队列是否为空:判断队列是否为空。...push方法直接调用LinkedList的push方法,pop则调用LinkedList的pop方法。peek方法返回栈顶元素,is_empty方法检查栈是否为空。...head指向队列的第一个元素,tail指向队列的最后一个元素。enqueue方法在队尾插入新元素,dequeue方法从队头删除元素。

    10410
    领券