基于
volatile有什么作用? http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#incorrectlySync
和
易失性的新保证 http://www.ibm.com/developerworks/library/j-jtp03304/
class VolatileExample {
int x = 0;
volatile boolean v = false;
public void writer() {
x = 42;
v = true;
}
public void reader() {
if (v == true) {
//uses x - guaranteed to see 42.
}
}
}
似乎。
1a) write to non-volatile variable x
1b) write to volatile variable v
1a永远不会移动传递1b
我想知道,如果我将源代码修改为以下
class VolatileExample {
int x = 42;
volatile boolean v = true;
public void writer() {
v = false;
x = 0;
}
public void reader() {
if (v == true) {
//uses x - guaranteed to see 42?????
}
}
}
可以置换以下序列吗?
2a) write to volatile variable v
2b) write to non-volatile variable x
我想知道,2b可以在2a之前移动吗?这是因为如果2b能够在2a之前移动,读者就不能再保证在if块内看到42。
我觉得2b可以在2a之前根据以下信息移动。
http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#reordering
写入易失性字段有 与监视器相同的记忆效应 释放,并从一个不稳定的阅读 字段具有与a相同的记忆效果 监控获取。
这意味着任何内存操作 以前可以看到一个帖子 退出同步块是 任何线程进入后都可见 由...保护的同步块 同样的显示器,因为所有的记忆 操作在发布之前发生, 并且释放发生在之前 获得。
和Roach Motels and The Java Memory Model
volatile_v = true; <-- monitor release
non_volatile_x = 42;
(volatile_v will act as a roach motels, and it is fine for non_volatile_x to move into roach motels)
non_volatile_x = 42;
volatile_v = true; <-- monitor release
(volatile_v will act as a roach motels, and it is not OK for non_volatile_x to move out from roach motels)
答案 0 :(得分:1)
我们知道,对于任何先前的读取或写入(从Java5开始),对volatile变量的写入都不能重新排序,但反过来却不是这样。所以将程序重新排序为x = 0; v = false;根据我的理解,这是正确的。
在我们写到v之后,我们保证在读取v时,在写入v之前发生的每个动作都是可见的,但是在写入v之后没有说明任何动作 - 那些可能发生也可能没发生甚至可以在写入v之前重新排序。
答案 1 :(得分:0)
易失性有两个部分,指令的顺序和写入的“刷新”。
指令的顺序不会改变,但两段代码之间可能有任何延迟,所以在第二种情况下x可能是42但它可能是0.我的猜测是你会经常看到0。
根据您的体系结构,这可能比在其他系统上更有可能,因此在一台计算机上测试它是42,并不意味着它总是在另一台计算机上。
答案 2 :(得分:0)
据我了解新的内存模型,一旦将volatile值刷新到主内存,刷新线程可以看到的所有其他变量也必须刷新。但结果是你的2b不能被VM重新排序到2a之前,因为这会违反代码中隐含的'before-before'排序。
答案 3 :(得分:0)
我认为你没有保证,因为类实例字段 x 没有被封装,并且包可见可以被另一个线程更改。使 x 变量 volatile 可以解决该问题并保证所有线程的可见性。
答案 4 :(得分:0)
语句2b(写入非易失性变量x)可以在语句2a之前移动(写入volatile变量v),也就是说,另一个线程可能会看到v==true
和x==0
)。
注意,即使没有重新排序另一个线程,也可能会看到这些值!
假设已创建并初始化VolatileExample
的实例。线程T1在该实例上执行方法reader
。它看到v == true
并被调度程序中断。第二个线程调用方法writer
现在可以执行分配v=false
和x=0
。当T1恢复并读取x
时,它可能会读取值0(但没有保证看到0)。如果它看到值0,那么我们就会看到T1看到v==true
和x==0
的情况。对于T1,看起来两个语句都已重新排序。由于可以在不重新排序的情况下观察到这种状态,因此实际上允许重新排序是有意义的。