Не удается получить это условие в исходном коде ConcurrentLinkedQueue

В исходном коде ConcurrentLinkedQueue, в offer метод:

public boolean offer(E e) {
checkNotNull(e);
final Node<E> newNode = new Node<E>(e);

for (Node<E> t = tail, p = t;;) {
    Node<E> q = p.next;
    if (q == null) {
        // p is last node
        if (p.casNext(null, newNode)) {
                // Successful CAS is the linearization point
                // for e to become an element of this queue,
                // and for newNode to become "live".
                if (p != t) // hop two nodes at a time
                    casTail(t, newNode);  // Failure is OK.
                    return true;
            }
            // Lost CAS race to another thread; re-read next
        }
        else if (p == q)
            // We have fallen off list.  If tail is unchanged, it
            // will also be off-list, in which case we need to
            // jump to head, from which all live nodes are always
            // reachable.  Else the new tail is a better bet.
            p = (t != (t = tail)) ? t : head;
        else
            // Check for tail updates after two hops.
            p = (p != t && t != (t = tail)) ? t : q;
    }
}

в строке 352 это условие:

p = (p != t && t != (t = tail)) ? t : q;

Я знаю, что код должен поставить p в хвост, но зачем использовать такой сложный код? и что делает (p != t && t != (t = tail))имею в виду? какая разница между t!=(t=tail)) а также t!=t? это всегда должно быть ложным?

Есть ли какие-либо материалы, которые могут четко объяснить ConcurrentLinkedQueue?

2 ответа

Это интересный вопрос, я задал его более широко и получил несколько ответов. Из того, что я могу прочитать по этой теме:

t != (t = tail) это просто странный способ написать:

if (t != tail)
    t = tail;

Короче говоря, вы сравниваете значение t со значением того, что назначено t справа здесь tail,

(Все кредиты идут к Eran за его понимание темы и его ответ)

Итак, чтобы ответить на ваш вопрос полностью:

  • Я не знаю, почему они использовали такой сложный код.
  • (p != t && t != (t = tail)) средства if p != t and if t != tail t takes the tail value
  • Разница объяснила
  • Это не должно быть всегда ложным (очевидно)

Поэтому я думаю, что другой поток может обновляться между операциями, которые

t != (t = tail))

проверяет, и это проверяет для этого. чтобы быть полезным, нужно полагаться на атомику

Редактировать:

ответить Ясине Бадаче, даунвот, который кажется правильным

t = tail

является оператором присваивания

так же

if

оператор используется для ветвления кода на основе условия, и

(x = y)

возвращает ссылку на x, как в (очевидно, по проверке любого, кто когда-либо использовал c)

if ((p = fopen(f)) == NULL)

Я думаю, что OP касается внутренней (или кто бы то ни было) внутренней реализации функциональности параллелизма

Редактировать:

и я думаю, что это ошибка в реализации Java и / или глупости

Другие вопросы по тегам