JCSprout
JCSprout copied to clipboard
关于AQS框架中addWaiter()方法的一点疑问。
/**
* Creates and enqueues node for current thread and given mode.
*
* @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
* @return the new node
*/
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
在 addWaiter() 这个方法中,JDK 为何要先用一次 CAS 尝试将新的 node 添加到队尾,而不直接调用 enq() 方法来入队呢? enq() 方法的实现也是使用 CAS 操作入队,自旋至入队成功才会退出。
/**
* Inserts node into queue, initializing if necessary. See picture above.
* @param node the node to insert
* @return node's predecessor
*/
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
并且两个方法存在一部分相同的代码,这样设计不会冗余吗?希望得到您的解答,谢谢~
单写的内容和循环的一样,不知道是不是创造循环有什么额外的消耗吧。看他们好多写法,或者参数都是根据经验来的。
我的看法是,先尝试一次CAS入列,如果竞争不激烈会直接成功,减少消耗
我的看法是,先尝试一次CAS入列,如果竞争不激烈会直接成功,减少消耗
你看下enq方法代码,如果直接enq,竞争不激烈的话也是直接成功,没有什么额外消耗
您的邮件我已收到,我会尽快查收回复。
这是来自qq邮箱的自动回复。 您好,感谢您的来信,您的邮件已经投递到该邮箱,但您看到这封回信不代表主人已经看到您的邮件,仅代表您的信件发送成功。 祝你快乐~