在阅读了更多的博客/文章等之后,我现在对内存障碍之前/之后加载/存储的行为感到非常困惑。
下面是Doug在他的一篇关于JMM的澄清文章中引用的两段话,这两篇文章都非常直截了当:
但是,当我查看另一个关于内存障碍的blog时,我得到了以下内容:
对我来说,Doug的澄清比另一个更加严格:基本上,这意味着如果负载屏障和存储屏障在不同的监视器上,数据一致性将得不到保证。但后者意味着即使在不同的监视器上设置了障碍,数据的一致性也将得到保证。我不确定我是否正确地理解了这2条,也不确定其中哪一条是正确的。
考虑到下列守则:
public class MemoryBarrier {
volatile int i = 1, j = 2;
int x;
public void write() {
x = 14; //W01
i = 3; //W02
}
public void read1() {
if (i == 3) { //R11
if (x == 14) //R12
System.out.println("Foo");
else
System.out.println("Bar");
}
}
public void read2() {
if (j == 2) { //R21
if (x == 14) //R22
System.out.println("Foo");
else
System.out.println("Bar");
}
}
}假设我们有一个写线程TW1首先调用MemoryBarrier的写()方法,然后我们有两个读取器线程TR1和TR2调用MemoryBarrier的read1()和read2() method.Consider这个程序运行在不保持顺序的CPU上(x86确实保留这种情况下的排序),根据内存模型,W01/W02之间将有一个StoreStore屏障(例如SB1),以及R11/R12和R21/R22之间的2 LoadLoad屏障(假设RB1和RB2)。
我不确定哪一个是正确的,或者两者都是正确的,但是Martin所描述的只是x86体系结构。JMM不能保证对x的更改对TR2是可见的,但是x86实现是可见的。
谢谢~
发布于 2014-06-28 18:33:12
道格·利亚是对的。您可以在Java语言规范的§17.4.4部分找到相关的部分
§17.4.4 Synchronization Order 。。对易失性变量v (§8.3.1.4)的写入与任何线程对v的所有后续读取同步(其中“后继”根据同步顺序定义)。。。
具体机器的内存模型并不重要,因为Java编程语言的语义是用抽象机器定义的--与具体机器无关。Java运行时环境有责任以这样的方式执行代码,使其符合Java语言规范提供的保证。
关于实际问题的:
read2方法可以打印"Bar",因为read2可以在write之前执行。CountDownLatch进行额外的同步以确保read2在write之后执行,那么方法read2将永远不会打印"Bar",因为与CountDownLatch的同步删除了x上的数据竞争。独立易失变量:
对易失性变量的写入与任何其他易失性变量的读取不同步,这是否合理?
是的,这很有道理。如果两个线程需要相互交互,它们通常必须使用相同的volatile变量来交换信息。另一方面,如果线程使用易失性变量而不需要与所有其他线程交互,我们不想为内存屏障付出代价。
实际上,这在实践中是很重要的。我们来举个例子吧。以下类使用一个易失性成员变量:
class Int {
public volatile int value;
public Int(int value) { this.value = value; }
}假设这个类仅在方法中本地使用。JIT编译器可以很容易地检测到,该对象仅在此方法(Escape analysis)中使用。
public int deepThought() {
return new Int(42).value;
}根据上述规则,JIT编译器可以删除volatile读写的所有效果,因为不能从任何其他线程访问volatile变量。
这种优化实际上存在于Java JIT编译器中:
发布于 2014-06-28 19:02:37
据我所知,这个问题实际上是关于易失性读/写及其发生-在保证之前。说到这部分,我只想补充诺西德的回答一件事:
在正常写入之前不能移动易失性写入,在正常读取之后不能移动易失性读。这就是为什么read1()和read2()的结果将如nosid所写的那样。
说到障碍--这个定义对我来说听起来不错,但可能让你感到困惑的是,这些东西/工具/方式/机制(不管你喜欢什么都可以)来实现在hotspot中用JMM描述的行为。在使用Java时,您应该依赖于JMM保证,而不是实现细节。
https://stackoverflow.com/questions/24469063
复制相似问题