찾다

 >  Q&A  >  본문

java - AbstractQueuedSynchronizer中CAS的疑惑

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

巴扎黑巴扎黑2813일 전691

모든 응답(2)나는 대답할 것이다

  • ringa_lee

    ringa_lee2017-04-18 10:54:59

    TZ가 CompareAndSetTail을 잘못 이해하고 있을 수 있습니다.

    으아아아

    AbstractQueuedSynchronizer의 tailOffset 위치에서 예상되는 노드 값과 pred 값을 비교합니다. 동일한 경우 tailOffset 위치의 값을 업데이트합니다.

    으아아아

    compareAndSetTail(pred, node) 이 코드가 실행된 후에는 AbstractQueuedSynchronizer 객체의 tailOffset 값, 즉 멤버 변수 tail의 값만 수정되며 pred의 값에는 영향을 미치지 않습니다. 이중 연결 리스트의 경우 tail 삽입에 논리적인 문제가 없습니다.

    회신하다
    0
  • PHPz

    PHPz2017-04-18 10:54:59

    이 디자인은 双向链表입니다.
    B.prev == A
    A.next == B

    compareAndSetTail 설정이 성공하면 tail을 현재 node으로 업데이트하면 됩니다. pred.next은 이전 테일 노드의 next을 현재 node로 설정하는데 문제가 없습니다. 논리.

    회신하다
    0
  • 취소회신하다