ConcurrentLinkedQueue 是一个基于链接节点的无界线程安全队列,它采用先进先出FIFO的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部,当我们获取一个元素时,它会返回队列头部的元素。它采用了“wait-free”算法。并且采用CAS操作,保证数据的一致性。
CAS是compare and set的缩写,意思是指在set值之前先比较改值有没有变化,只有在没变化的情况下才对其赋值。
入队源码:
public boolean offer(E e) {
//判断元素是否为空
checkNotNull(e);
//入队前,创建一个新节点
final Node<E> newNode = new Node<E>(e);
// 创建一个指向tail节点的引用
// 用p来表示队列的尾节点
for (Node<E> t = tail, p = t;;) {
//获取p节点的下一个节点
Node<E> q = p.next;
if (q == null) {
// q为null,表示p节点为尾节点,无下一个节点
if (p.casNext(null, newNode)) {
// 原子操作,如果下一个值为null,则next改变为newNode的值
if (p != t) // 如果此时tail节点有大于等于1个节点,p节点不是tail节点,则将入队节点设置成tail节点。
casTail(t, newNode); // 允许更新失败,如果失败表示有其他线程更新了tail节点。
return true;
}
// Lost CAS race to another thread; re-read next
}
else if (p == q)
// p==q 表示节点p已经从队列里移除。如果tail没有被修改,它也被从队列移除。
// (可能当前队列中没有数据存在,所以返回head节点)
p = (t != (t = tail)) ? t : head;
else
// 节点P仍然在队列上,且不是最后节点,p向前移
// 在两跳之后检测tail的更新
p = (p != t && t != (t = tail)) ? t : q;
}
}
AtomicLong:对长整形进行原子操作。
在32位操作系统中,64位的long和double变量由于会被JVM当做两个分离的32位来进行操作,所以不具备原子性。