1、入队列enq方法
/**
* Inserts node into queue, initializing if necessary. See picture above.
* @param node the node to insert(待插入的节点)
* @return node's predecessor(前任节点)
*/
//todo 当第一个节点入队列的时候需要debug查看情况
private Node enq(final Node node) {
for (;;) { //自旋
Node t = tail; //临时的对象引用,指向尾节点
//如果临时的对象引用为null,说明队列没有元素
if (t == null) { // Must initialize
//cas设置头节点为 重写new的一个节点,设置成功或者失败都再次循环,因为没返回值
if (compareAndSetHead(new Node()))
tail = head; //设置头节点成功,将头节点赋值给尾节点,此时都节点和尾节点都指向当前入参节点,但是节点没建立关系
} else { //尾节点不为null
node.prev = t; //将当前节点的前任节点设置为尾节点(即插入到队列的尾部)
if (compareAndSetTail(t, node)) {//cas设置尾节点为当前节点,设置失败再次循环
t.next = node; //将之前的尾巴节点(t,即现在队列的倒数第二个节点),t的下一个节点指向新的尾巴节点(即当前入参节点node)
return t; //返回前任节点
}
}
}
}
aqs-enq.png