java - AbstractQueuedSynchronizer中CAS的疑惑
巴扎黑
巴扎黑 2017-04-18 10:52:59
0
2
614

这段代码是AQS框架中将当前节点入队的操作。

Node pred = tail; if (pred != null) { node.prev = pred; if (compareAndSetTail(pred, node)) { pred.next = node; return node; } }

上面代码中pred被赋值为尾节点,node为当前节点。我理解的将新节点插入链表尾处的逻辑应当如下:
node.prev = pred; node节点的前驱指向尾节点
pred.next = node; 将尾节点的后继设置为当前节点
tail = node; 将node节点设置为尾节点
对于上面代码我的疑问如下:
如果尾节点不为空,node节点的前驱会指向尾节点,然后调用CAS交换pred和node的值。
此时pred(即tail)的值应该已经是当前节点node的值了,再执行pred.next=node是什么意思呢,这是否存在逻辑问题?

巴扎黑
巴扎黑

全員に返信 (2)
左手右手慢动作

TZ可能对compareAndSetTail的理解有误。

private final boolean compareAndSetTail(Node expect, Node update) { return unsafe.compareAndSwapObject(this, tailOffset, expect, update); }

在AbstractQueuedSynchronizer的tailOffset位置比较pred的值和期望的node值,如果相同则更新tailOffset位置的值。

static { tailOffset = unsafe.objectFieldOffset (AbstractQueuedSynchronizer.class.getDeclaredField("tail")); ... }

compareAndSetTail(pred, node) 这句代码执行完成之后,被修改只是对象AbstractQueuedSynchronizer的tailOffset的值,也就是成员变量tail的值,对于pred的值没有任何影响。至于双向链表,尾部插入,逻辑上没有问题。

いいねを押す+0
    PHPzhong

    这个设计是一个双向链表.
    B.prev == A
    A.next == B

    compareAndSetTail设置成功只是将tail更新为当前node.pred.next是将上一个尾部节点的next设置为当前node这逻辑不存在问题.

    いいねを押す+0
      最新のダウンロード
      詳細>
      ウェブエフェクト
      公式サイト
      サイト素材
      フロントエンドテンプレート
      私たちについて 免責事項 Sitemap
      PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!