Не удается получить это условие в исходном коде 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 и / или глупости