JLS的memory model section (17.4)合理详细地描述了volatile和非volatile读写的语义,以及与某些其他构造(例如监视器进入和退出)的交互。

但是,它没有完全解释java.util.concurrent.Atomic *类上compareAndSwaplazySet的语义。对于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提供了更加难以理解的blurb:
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 ExpectedValue与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在这里可能吗?的确,val1val2可以是10吗?

锁存器不是问题的核心-它们只是让两个线程都等到另一个线程完成,然后强制在每个线程上有趣的lazySetcompareAndSet操作之间进行操作,以及稍后读取原子的一种方式以查看状态(没有它们,您肯定可以至少暂时看到val2 == 10)。

最佳答案

compareAndSet既是读取又是写入,因此它确实施加了写入顺序约束。根据文档,这意味着lazySet写入将被而不是围绕其重新排序。因此,不,val1val2永远不应为10。

编辑:澄清一下,lazySet本质上所做的是,它为任何也写入同一事物的其他原子操作目的而执行原子写入,但对于仅读取的其他原子操作则非原子操作。

AtomicInteger lazySet vs. set上可能有更多有用的讨论,最有用的花絮是指向原始变更集的链接,其中添加了惰性方法:http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6275329

07-25 20:17