有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java原子比较和交换能在看不到的情况下覆盖惰性写操作吗?

JLS的memory model section (17.4)合理详细地描述了volatile和非volatile读写的语义,以及与某些其他构造(如monitor enter和exit)的交互

然而,它并没有完全解释java上compareAndSwaplazySet的语义。util。同时发生的原子*类。对于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)和懒散集发布到相同的原子值,其中CAS expectedValue不同于懒散集值,那么CAS是否可能覆盖懒散集值

更明确地说,给定在公共AtomicInteger atomic = new AtomicInteger();上操作的两个线程T1和T2,如下所示:

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


共 (1) 个答案

  1. # 1 楼答案

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

    编辑:澄清一下,lazySet本质上的作用是,它为任何其他原子操作充当原子写操作,也将写入同一事物,但为其他仅为读取的原子操作充当非原子写操作

    AtomicInteger lazySet vs. set上进行了更有用的讨论,最有用的小贴士是指向添加了惰性方法的原始变更集的链接:http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6275329