并发队列
ConcurrentLinkedQueue
无界的并发队列,内部用单向链表实现。核心源码如下
//节点
private static class Node<E> {
volatile E item;
volatile Node<E> next;
//创建node时不会有并发问题,直接写入元素
Node(E item) {
UNSAFE.putObject(this, itemOffset, item);
}
......
}
//队头指针
private transient volatile Node<E> head;
//队尾指针
private transient volatile Node<E> tail;
public ConcurrentLinkedQueue() {
//初始头和尾都指向空节点
head = tail = new Node<E>(null);
}
//入队
public boolean offer(E e) {
//空指针检查
checkNotNull(e);
final Node<E> newNode = new Node<E>(e);
for (Node<E> t = tail, p = t;;) {
//q指向p的后继
Node<E> q = p.next;
if (q == null) {//p是最后一个节点
if (p.casNext(null, newNode)) {//CAS操作,将newNode入队,直到成功为止
if (p != t) //进入这个if分支说明 第一次循环p不是tail节点,走了外层else分支向后移动(其他线程入队);
//CAS操作,将tail指向newNode,失败了也没关系,等下一个入队线程更新。
casTail(t, newNode);
return true;
}
// CAS失败了会由其他线程重新读取
}
else if (p == q)
//到达队尾
p = (t != (t = tail)) ? t : head;
else
//p不是最后一个节点,p移到下个位置
p = (p != t && t != (t = tail)) ? t : q;
}
}
//出队
public E poll() {
restartFromHead:
for (;;) {
for (Node<E> h = head, p = h, q;;) {
E item = p.item;
//CAS操作,将p的item成功置为null,就算出队
if (item != null && p.casItem(item, null)) {
if (p != h) // 进入这个if分支说明 第一次循环p不是head节点,走了外层else分支向后移动(其他线程出队);
//CAS操作,如果p的后继不为空则head置为p的后继,否则置为p,失败也没关系,等下一个出队线程更新
updateHead(h, ((q = p.next) != null) ? q : p);
return item;
}
else if ((q = p.next) == null) {//如果队列中为空
updateHead(h, p);
return null;
}
else if (p == q)
continue restartFromHead;
else
p = q;
}
}
}