Я читаю Java Параллелизм на практике и встречаю 15.7 Вставка в алгоритм неблокирующей очереди Майкла-Скотта. .
package net.jcip.examples;
import java.util.concurrent.atomic.*;
import net.jcip.annotations.*;
/**
* LinkedQueue
* <p/>
* Insertion in the Michael-Scott nonblocking queue algorithm
*
* @author Brian Goetz and Tim Peierls
*/
@ThreadSafe
public class LinkedQueue <E> {
private static class Node <E> {
final E item;
final AtomicReference<LinkedQueue.Node<E>> next;
public Node(E item, LinkedQueue.Node<E> next) {
this.item = item;
this.next = new AtomicReference<LinkedQueue.Node<E>>(next);
}
}
private final LinkedQueue.Node<E> dummy = new LinkedQueue.Node<E>(null, null);
private final AtomicReference<LinkedQueue.Node<E>> head
= new AtomicReference<LinkedQueue.Node<E>>(dummy);
private final AtomicReference<LinkedQueue.Node<E>> tail
= new AtomicReference<LinkedQueue.Node<E>>(dummy);
public boolean put(E item) {
LinkedQueue.Node<E> newNode = new LinkedQueue.Node<E>(item, null);
while (true) {
LinkedQueue.Node<E> curTail = tail.get();
LinkedQueue.Node<E> tailNext = curTail.next.get();
if (curTail == tail.get()) { // what is the purpose of this check?
if (tailNext != null) {
// Queue in intermediate state, advance tail
tail.compareAndSet(curTail, tailNext);
} else {
// In quiescent state, try inserting new node
if (curTail.next.compareAndSet(null, newNode)) {
// Insertion succeeded, try advancing tail
tail.compareAndSet(curTail, newNode);
return true;
}
}
}
}
}
}
Если у нас есть if (curTail == tail.get())
проверьте, мы можем узнать, был ли tail
изменен после LinkedQueue.Node<E> curTail = tail.get();
, если tail
был изменен, выполните while
l oop снова. Но если мы пропустим эту проверку и tail
был изменен после LinkedQueue.Node<E> curTail = tail.get();
, мы потерпим неудачу в tail.compareAndSet(curTail, tailNext);
или curTail.next.compareAndSet(null, newNode)
, мы снова выполним while
l oop, , поэтому результат будет так же, как наличие чека .
Итак, есть ли другие различия между наличием или отсутствием этого чека? Можем ли мы просто опустить этот чек?