Skip to content

Latest commit

 

History

History
28 lines (15 loc) · 1.95 KB

ConcurrentLinkedQueue.md

File metadata and controls

28 lines (15 loc) · 1.95 KB

ConcurrentLinkedQueue

如果要实现一个线程安全的队列有两种方式:

  • 使用阻塞算法,用一个锁(入队和出对用一个锁)或两个锁(入队和出对用不同的锁)等方式来实现

  • 使用非阻塞性算法,使用循环 CAS 的方式来实现

ConcurrentLinkedQueue 是一个基于链接节点的无界线程安全队列,它采用的是先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部;当我们获取一个元素时,它会返回队列头部的元素。 它采用了 “wait-free” 算法(即 CAS 算法)来是实现。

结构

ConcurrentLinkedQueue 由 head 节点和 tail 节点组成,每个节点(Node)由节点元素(value)和指向下一个节点(next)的引用组成。默认情况下 head 节点存储的值为空,tail 节点等于 head 节点。

入队列

入队列就是将入队节点添加到队列的尾部。

  1. 将入队节点设置成当前队列尾节点的下一个节点

  2. 更新 tail 节点,如果 tail 节点的 next 节点不为空,则将入队节点设置为 tail 节点,如果 tail 节点的 next 节点为空,则将入队节点设置为 tail 的 next 节点,所以 tail 节点不总是尾结点

出队列

并不是每次出列时都更新 head 节点,当 head 节点里有元素时,直接弹出 head 节点里的元素,而不会更新 head 结点。只有 head 节点里没有元素时,出队操作才会更新 head 节点。

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