一、ConcurrentLinkedQueue(线程安全的队列)适用于并发编程中。
A.实现线程安全的队列有两种实现方式:一种是使用阻塞算法队列,另一种是使用非阻塞算法队列
阻塞算法队列:可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现
非阻塞算法队列:可以使用循环CAS的方式来实现
实例:非阻塞算法队列实现,如:ConcurrentLinkedQueue
ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部,当我们获取一个元素时,它会返回队列头部的元素。它采用了“wait-free”算法来实现,该算法在Michael & Scott算法上进行了一些修改。
ConcurrentLinkedQueue由head节点和tail节点组成,每个节点(Node)由节点元素(item)和指向下一个节点的引用(next)组成,节点与节点之间就是通过这个next关联起来,从而组成一张链表结构的队列。
***举例***:ConcurrentLinkedQueue的 方法1:add(E e) 入队方法 分析
从源代码角度来看整个入队过程主要做两件事情:
1、定位出尾节点:tail节点并不总是尾节点,所以每次入队都必须先通过tail节点来找到尾节点,尾节点可能就是tail节点,也可能是tail节点的next节点
2、使用CAS算法能将入队节点设置成尾节点的next节点,如不成功则重试:p.casNext(null, newNode)方法用于将入队节点设置为当前队列尾节点的next节点,q如果是null表示p是当前队列的尾节点,如果不为null表示有其他线程更新了尾节点,则需要重新获取当前队列的尾节点。
ConcurrentLinkedQueue的add(E e) 出队方法 分析
从队列里返回一个节点元素,并清空该节点对元素的引用:首先获取头节点的元素,然后判断头节点元素是否为空,如果为空,表示另外一个线程已经进行了一次出队操作将该节点的元素取走,如果不为空,则使用CAS的方式将头节点的引用设置成null,如果CAS成功,则直接返回头节点的元素,如果不成功,表示另外一个线程已经进行了一次出队操作更新了head节点,导致元素发生了变化,需要重新获取头节点。
ConcurrentLinkedQueue的 其他方法:
peek()方法:获取链表的首部元素(只读取而不移除),peek操作会改变head指向,执行peek()方法后head会指向第一个具有非空元素的节点。
size()方法:获取当前队列的元素个数,但在并发环境中,其结果可能不精确,因为整个过程都没有加锁,所以从调用size方法到返回结果期间有可能增删元素,导致统计的元素个数不精确。
remove(Object o)方法:删除的元素不能为null
contains(Object o)方法:遍历队列,若找到匹配节点,则返回true,该方法和size方法类似,有可能返回错误结果,比如调用该方法时,元素还在队列里面,但是遍历过程中,该元素被删除了,那么就会返回false。
线程安全队列技术图:
ConcurrentLinkedQueue基于CAS的无锁技术,不需要在每个操作时使用锁,所以扩展性表现要更加优异,在常见的多线程访问场景,一般可以提供较高吞吐量
LinkedBlockingQueue内部则是基于锁,并提供了BlockingQueue的等待性方法
二、J.U.C完整技术架构:
java.util.concurrent(J.U.C)包按照功能可划分如下:
1.juc-locks 锁框架
2.juc-atomic 原子类框架
3.juc-sync 同步器框架
4.juc-collections 集合框架
5.juc-executors 执行器框架
1.juc-locks 锁框架:对synchronizd、wait、notify等进行补充、增强
- J.U.C之locks框架(1):接口说明
- J.U.C之locks框架(2):ReentrantLock 的使用
- J.U.C之locks框架(3):ReentrantReadWriteLock 的使用
- J.U.C之locks框架(4):LockSupport 工具类
- J.U.C之locks框架(5):AbstractQueuedSynchronizer 综述
- J.U.C之locks框架(6):AbstractQueuedSynchronizer 的独占功能原理
- J.U.C之locks框架(7):Condition 原理
- J.U.C之locks框架(8):AbstractQueuedSynchronizer 的共享功能原理
- J.U.C之locks框架(9):ReentrantReadWriteLock 原理
- J.U.C之locks框架(10):更强的读写锁——StampedLock
2.juc-atomic 原子类框架:通过一种“无锁算法”,线程安全的操作Integer、Long、Boolean等原始类型
无锁算法:通过Unsafe类实现的一种比较并交换的算法:boolean compareAndSet(expectedValue, updateValue);
- J.U.C之atomic框架(1):Unsafe类
- J.U.C之atomic框架(2):AtomicInteger
- J.U.C之atomic框架(3):AtomicReference
- J.U.C之atomic框架(4):Atomic数组
- J.U.C之atomic框架(5):AtomicXXXFieldUpdater
- J.U.C之atomic框架(6):更强的原子类——LongAdder
3.juc-sync 同步器框架
- J.U.C之synchronizer框架(1):倒数计数器——CountDownLatch
- J.U.C之synchronizer框架(2):循环栅栏——CyclicBarrier
- J.U.C之synchronizer框架(3):信号量——Semaphore
- J.U.C之synchronizer框架(4):数据交换器——Exchanger
- J.U.C之synchronizer框架(5):多阶段栅栏——Phaser
4.juc-collections 集合框架:按类型划分可以分为:符号表、队列、Set集合、列表四大类
- J.U.C之collections框架(1):ConcurrentHashMap的基本原理
- J.U.C之collections框架(2):ConcurrentHashMap的扩容
- J.U.C之collections框架(3):跳表——ConcurrentSkipListMap
- J.U.C之collections框架(4):ConcurrentSkipListSet
- J.U.C之collections框架(5):“写时复制”的应用——CopyOnWriteArrayList
- J.U.C之collections框架(6):CopyOnWriteArraySet
- J.U.C之collections框架(7):无锁队列——ConcurrentLinkedQueue
- J.U.C之collections框架(8):无锁双端队列——ConcurrentLinkedDeque
- J.U.C之collections框架(9):阻塞队列简介——BlockingQueue
- J.U.C之collections框架(10):基于数组的阻塞队列——ArrayBlockingQueue
- J.U.C之collections框架(11):基于单链表的阻塞队列——LinkedBlockingQueue
- J.U.C之collections框架(12):基于堆的优先级阻塞队列——PriorityBlockingQueue
- J.U.C之collections框架(13):特殊的同步队列——SynchronousQueue
- J.U.C之collections框架(14):延时阻塞队列——DelayQueue
- J.U.C之collections框架(15):基于双链表的阻塞双端队列——LinkedBlockingDeque
- J.U.C之collections框架(16):LinkedTransferQueue
5.juc-executors 执行器框架:executors框架是整个J.U.C包中类/接口关系最复杂的框架,executors其实可以划分为3大块,每一块的核心都是基于Executor这个接口
a.线程池
b.Future模式
c.Fork/Join框架
J.U.C之executors框架(1):executors框架概述
J.U.C之executors框架(2):普通线程池——ThreadPoolExecutor
J.U.C之executors框架(3):计划线程池——ScheduledThreadPoolExecutor
J.U.C之executors框架(4):Future 模式
J.U.C之executors框架(5):Fork/Join 框架的原理
J.U.C之executors框架(6):Fork/Join 框架的实现