欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java并发编程的艺术:(6)Java 并发容器和框架之 ConcurrentLinkedQueue

程序员文章站 2022-05-13 15:09:51
...


在并发编程中,有时候需要使用线程安全的队列。如果要实现一个线程安全的队列有两种方式:一种是使用阻塞算法,另一种是使用非阻塞算法。使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队使用不同的锁)等方式来实现。非阻塞的实现方式则可以使用循环 CAS 的方式来实现。

ConcurrentLinkedQueue 是一个机遇链接节点的*线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,他会添加到队列的尾部;当我们获取一个元素时,它会返回队列头部的元素。它采用了 “wait-free” 算法(CAS)来实现,该算法在 Michael & Scott 算法基础上进行了一些修改。

ConcurrentLinkedQueue 的结构

ConcurrentLinkedQueue 由 head 节点和 tail 节点组成,每个节点(Node)由节点元素(item)和指向下一个节点(next)的引用组成,节点之间就是通过这个 next 关联起来,从而组成一张链表结构的队列。默认情况下 head 节点存储的元素为空, tail 节点等于 head 节点。

private transient volatile Node<E> tail = head;

入队列

入队列就是将入队节点添加到队列的尾部。插入的过程就是数据结构中学习的队列的操作,不过这里边在 tail 节点插入时采用了 CAS 算法保证线程安全。

出队列

出队列首先获取头节点的元素,然后判断头节点元素是否为空,如果为空,表示另外一个线程已经进行了一次出队操作将该节点的元素去走,如果不为空,则使用 CAS 的方法将头节点的引用设置为 null,如果 CAS 成功,则直接返回头节点的元素,如果不成功,表示另外一个线程已经进行了一次出队操作更新了 head 节点,导致元素发生了变化,需要重新获取头节点。

学过数据结构之后,这部分内容非常容易理解,ConcurrentLinkedQueue 跟普通的队列区别在于,为了保证并发下的线程安全,对队列的修改操作采用了 CAS 算法,仅此而已。

参考

《Java 并发编程的艺术》

相关标签: 并发编程的艺术