2015-01-27 6 views
6

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, временно).

ответ

2

compareAndSet - это как чтение, так и запись, поэтому оно налагает ограничение порядка записи. В документах это означает, что lazySet будет писать , а не, чтобы его можно было переупорядочить вокруг него. Так нет, val1 и val2 никогда не должны быть 10.

EDIT: Для того, чтобы уточнить, какие lazySet по существу делает то, что он действует атомную запись для целей любых других атомарных операций, которые также пишет то же самое, но неатомные для других атомных операций, которые только .

Более потенциально полезное обсуждение на AtomicInteger lazySet vs. set, самые полезные пикантный быть ссылкой на оригинальную ревизию, где были добавлены ленивые методы: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6275329

+0

справа, но вопрос на самом деле не о повторном упорядочении: действительно 'lazySet' и' compareAndSwap' не встречаются в одном потоке, поэтому между ними нет никакого неотъемлемого порядка. Они будут возникать в некотором порядке, и вопрос более или менее связан с тем, что атомная природа CAS означает, что никогда не будет сжимать запись. – BeeOnRope

+0

Заказ здесь относится к операциям памяти, а не к инструкциям; нить которых они не являются фактором. CAS - это загрузка и хранилище, так как lazySet применяет _предохранительный барьер магазина-магазина, если CAS уже произошел, тогда запись будет завершена до того, как lazySet обновит ее. – tzaman

+0

Да - это единственные соответствующие инструкции. Какой поток, на котором они находятся, важен - в той же теме не было бы проблем.С другой стороны, две операции в разных потоках не имеют неотъемлемого порядка. В основном это утверждение вроде: «это означает, что запись lazySet не будет разрешена для переупорядочения вокруг него» имеет смысл для двух операций в одном и том же потоке, но в разных потоках они могут встречаться в любом порядке, кроме ограничений, накладываемых любым фактическим " синхронизируется с «операциями во время выполнения (например, волатильное чтение, которое видит волатильную запись из другого потока). – BeeOnRope