Когда объединитель применяет узел
Код: Выделить всё
class Node {
volatile Function action; //Used through its VarHandle
volatile Node next;
R item; // plain field
public void spItem(R item) { this.item = item; }
public R lpItem() { return item; }
void soAction(Function action) { ACTION.setRelease(this, action); }
boolean isApplied() { return ACTION.getAcquire(this) == null; }
}
Код: Выделить всё
//In a lock
Node curr;
curr.spItem(a.apply(item)); // plain write to result
curr.soAction(null); // release signals completion of the write
Чего я не понимаю, так это того, почему объединителю также необходимо это ограничение получения при проверке своего собственного узла:
Код: Выделить всё
// Still inside the lock, after the combine loop
return ours.lpItem(); // plain read, why does this return a stale value from earlier?
Мое нынешнее рассуждение состоит в том, что объединитель применяет свой собственный узел во время сканирования с простой записью в элемент, и поскольку это тот же поток, который читает его обратно, я ожидаю, что порядок программы будет гарантировать видимость без каких-либо ограничений. Есть ли что-то, что я здесь упускаю?
Примечание: это проявляется только при высоком параллелизме (более 32 потоков в моем тесте JMH). При меньшем числе потоков объединитель всегда считывает правильное значение.
Мобильная версия