Как показано ниже в FutureTask.java
( Jdk1.7 ):
/**
* Tries to unlink a timed-out or interrupted wait node to avoid
* accumulating garbage. Internal nodes are simply unspliced
* without CAS since it is harmless if they are traversed anyway
* by releasers. To avoid effects of unsplicing from already
* removed nodes, the list is retraversed in case of an apparent
* race. This is slow when there are a lot of nodes, but we don't
* expect lists to be long enough to outweigh higher-overhead
* schemes.
*/
private void removeWaiter(WaitNode node) {
if (node != null) {
node.thread = null;
retry:
for (;;) { // restart on removeWaiter race
for (WaitNode pred = null, q = waiters, s; q != null; q = s) {
s = q.next;
if (q.thread != null)
pred = q;
else if (pred != null) {
pred.next = s;
if (pred.thread == null) // check for race
continue retry;
}
else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,
q, s))
continue retry;
}
break;
}
}
}
Мы можем найти, что есть два комментария:
проверка на расу
И
перезапустить на RemoveWaiter race
Это простое изображение, на котором показано изменение состояния в removeWaiter
:
Есть мое понимание и вопрос:
Состояние гонки : Когда поток успешно находит узел pred
, а другой поток пытается удалить узел pred
, гонка происходит.
В моем мнении : q.next
, q.thread
и pred.thread
оба volitile
, поэтому, если текущий поток продолжает гонку с другими потоками, результат также будет действительным.
Вопрос : Почему Даг Ли выбрал перезапустить гонку вместо продолжить гонку , или по моему мнению что-то не так?