//非阻塞,一个基于链接节点的无界线程安全队列
public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
implements Queue<E>, java.io.Serializable {
private static final long serialVersionUID = 196745693267521676L;
//头节点
private transient volatile Node<E> head;
//尾结点
private transient volatile Node<E> tail;
//链表节点
private static class Node<E> {
volatile E item;//元素
volatile Node<E> next;//后继节点
Node(E item) {
UNSAFE.putObject(this, itemOffset, item);
}
boolean casItem(E cmp, E val) {
return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
}
// 设置next域的值,并不会保证修改对其他线程立即可见
void lazySetNext(Node<E> val) {
UNSAFE.putOrderedObject(this, nextOffset, val);
}
// 比较并替换next域的值
boolean casNext(Node<E> cmp, Node<E> val) {
return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
}
}
/**
* Tries to CAS head to p. If successful, repoint old head to itself
* as sentinel for succ(), below.
*/
final void updateHead(Node<E> h, Node<E> p) {
if (h != p && casHead(h, p))
h.lazySetNext(h);//h的next域指向它自己
}
/**
* Returns the successor of p, or the head node if p.next has been
* linked to self, which will only be true if traversing with a
* stale pointer that is now off the list.
*/
final Node<E> succ(Node<E> p) {
Node<E> next = p.next;
return (p == next) ? head : next;
}
/**
* 如果tail节点的next节点不为空,则将入队节点设置成tail节点,
* 如果tail节点的next节点为空,则将入队节点设置成tail的next节点,
* 所以tail节点不总是尾节点.
*/
//在队列尾插入元素
public boolean offer(E e) {
checkNotNull(e);//元素非null
final Node<E> newNode = new Node<E>(e);
for (Node<E> t = tail, p = t;;) {
Node<E> q = p.next;
if (q == null) {//p为尾结点
//p节点的next域指向newNode
if (p.casNext(null, newNode)) {
if (p != t)
casTail(t, newNode);
return true;
}
}
else if (p == q)
p = (t != (t = tail)) ? t : head;
else
// Check for tail updates after two hops.
//p == t --> p = q 否则尾结点被其他线程修改 p = tail
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;
// item不为null并且比较并替换item成功
if (item != null && p.casItem(item, null)) {
if (p != h)//表头发生变化,更新表头
updateHead(h, ((q = p.next) != null) ? q : p);
return item;
} // 表头的下一个节点为null,即链表只有一个“内容为null的表头节点”。则更新表头为p,并返回null
else if ((q = p.next) == null) {
updateHead(h, p);
return null;
}
else if (p == q)
continue restartFromHead;
else
p = q;
}
}
}
//从队列中移除指定元素
public boolean remove(Object o) {
if (o == null) return false;
Node<E> pred = null;
// 获取第一个存活的结点
for (Node<E> p = first(); p != null; p = succ(p)) {
E item = p.item;
// 找到item相等的结点,并且将该结点的item设置为null
if (item != null &&
o.equals(item) &&
p.casItem(item, null)) {
Node<E> next = succ(p);
if (pred != null && next != null)
pred.casNext(p, next);
return true;
}
pred = p;
}
return false;
}
}
ConcurrentLinkedQueue源码阅读
最新推荐文章于 2022-09-12 15:04:53 发布