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

这段代码是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是什么意思呢,这是否存在逻辑问题?

巴扎黑
巴扎黑

répondre à tous(2)
左手右手慢动作

TZ peut avoir une mauvaise compréhension de compareAndSetTail.

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

Comparez la valeur de pred avec la valeur de nœud attendue à la position tailOffset de AbstractQueuedSynchronizer. Si elles sont identiques, mettez à jour la valeur à la position tailOffset.

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

compareAndSetTail(pred, node) Une fois l'exécution de ce code terminée, seule la valeur de tailOffset de l'objet AbstractQueuedSynchronizer est modifiée, qui est la valeur de la variable membre tail, et n'a aucun effet sur la valeur de pred. Quant à la liste doublement chaînée, il n’y a aucun problème logique avec l’insertion de la queue.

PHPzhong

Ce design est un 双向链表.
B.prev == A
A.next == B

compareAndSetTail Si le réglage réussit, il met simplement à jour tail vers le node actuel et définit le pred.next du nœud de queue précédent sur le next actuel. la logique node

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!