memory model section (17.4) JLS описывает в разумных пределах семантику volatile
и не volatile
считывает и записывает, а также взаимодействие с некоторыми другими конструкциями, такими как вход и выход монитора.Может ли атомное сравнение и обмен перезаписывать ленивую запись, не видя ее?
Однако он не полностью объясняет семантику compareAndSwap
или lazySet
на java.util.concurrent.Atomic * classes. Для compareAndSet
, вы должны аннотацию от package javadoc:
compareAndSet and all other read-and-update operations such as getAndIncrement
have the memory effects of both reading and writing volatile variables.
lazySet
предлагает несколько более непроницаемое аннотацию:
lazySet has the memory effects of writing (assigning) a volatile variable
except that it permits reorderings with subsequent (but not previous)
memory actions that do not themselves impose reordering constraints with
ordinary non-volatile writes. Among other usage contexts, lazySet may apply
when nulling out, for the sake of garbage collection, a reference that is
never accessed again.
Что мне не ясно, как они взаимодействуют между собой. Если вы выдаете CAS (compareAndSet
) и lazySet с тем же атомным значением, где ожидаемый валид CAS отличается от значения lazySet, возможно ли, что CAS перезаписывает значение lazySet?
Более точно, учитывая две нити, T1 и T2, работающий на общей AtomicInteger atomic = new AtomicInteger();
следующим образом:
static CountDownLatch latch = new CountDownLatch(2);
T1
atomic.lazySet(5); // L1A
latch.countDown();
latch.await();
int val1 = atomic.get();
T2
atomic.compareAndSet(0, 10); // L2A
latch.countDown();
latch.await();
int val2 = atomic.get();
ли val1 == val2 == 10
возможный сценарий здесь? Действительно, может val1
илиval2
когда-нибудь 10?
Защелки не являются основанием для вопроса - это всего лишь способ, чтобы обе нити подождали, пока другая не будет выполнена, и заставляя произойти прежде между интересными операциями и compareAndSet
по каждому потоку, а позднее читает атом, чтобы увидеть состояние (без них вы наверняка увидите, по крайней мере, val2 == 10
, временно).
справа, но вопрос на самом деле не о повторном упорядочении: действительно 'lazySet' и' compareAndSwap' не встречаются в одном потоке, поэтому между ними нет никакого неотъемлемого порядка. Они будут возникать в некотором порядке, и вопрос более или менее связан с тем, что атомная природа CAS означает, что никогда не будет сжимать запись. – BeeOnRope
Заказ здесь относится к операциям памяти, а не к инструкциям; нить которых они не являются фактором. CAS - это загрузка и хранилище, так как lazySet применяет _предохранительный барьер магазина-магазина, если CAS уже произошел, тогда запись будет завершена до того, как lazySet обновит ее. – tzaman
Да - это единственные соответствующие инструкции. Какой поток, на котором они находятся, важен - в той же теме не было бы проблем.С другой стороны, две операции в разных потоках не имеют неотъемлемого порядка. В основном это утверждение вроде: «это означает, что запись lazySet не будет разрешена для переупорядочения вокруг него» имеет смысл для двух операций в одном и том же потоке, но в разных потоках они могут встречаться в любом порядке, кроме ограничений, накладываемых любым фактическим " синхронизируется с «операциями во время выполнения (например, волатильное чтение, которое видит волатильную запись из другого потока). – BeeOnRope