java - 原子比较和交换是否可以在看不到惰性写入的情况下覆盖它?

标签 java concurrency jls java-memory-model

memory model section (17.4) JLS 的描述合理详细地描述了 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 提供了更难理解的内容:

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,它们在公共(public) 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 吗?

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

最佳答案

compareAndSet 既是读又是写,因此它确实强加了写顺序约束。根据文档,这意味着 lazySet 写入将被允许围绕它重新排序。所以不,val1val2 永远不应该是 10。

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

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

关于java - 原子比较和交换是否可以在看不到惰性写入的情况下覆盖它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28164581/

相关文章:

java - 通过 Hibernate(不是 JDBC)从 blob 中检索图像

java/eclipse : org. apache.commons.lang.math 添加到构建路径后未解析

java - java中的参数和项目

java - 为 Java 的 lambda 体提供 this 关键字会出现什么问题?

java - Lambda表达式和方法重载的疑惑

java - 使用 Ormlite createOrUpdate() 方法获取 "UNIQUE constraint failed"异常

java - 并发求和列表,由另一个线程填充

应用 java AtomicIntegeraccumulateAndGet

javascript - 如何同步声明 JS 对象,然后使用依赖于并发操作的数据编辑对象的属性

java - 为什么我没有在以下代码中引用不明确的方法?