yet*_*der 14 java multithreading constructor processor-architecture memory-visibility
我正在尝试在非最终字段的对象初始化不足的情况下重现内存可见性问题(JLS 17.5 Final Field Semantics,FinalFieldExample类示例).它声明"但是,fy不是最终的;因此,reader()方法不能保证看到它的值4"
我试过这段代码:
public class ReorderingTest2 {
public static void main(String[] args) {
for (int i = 0; i < 2500; i++) {
new Thread(new Reader(i)).start();
new Thread(new Writer(i)).start();
}
}
static class Reader implements Runnable {
private String name;
Reader(int i) {
this.name = "reader" + i;
}
@Override
public void run() {
//System.out.println(name + " started");
while (true) {
FinalFieldExample.reader(name);
}
}
}
static class Writer implements Runnable {
private String name;
Writer(int i) {
this.name = "writer" + i;
}
@Override
public void run() {
//System.out.println(name + " started");
while (true) {
FinalFieldExample.writer();
}
}
}
static class FinalFieldExample {
int x;
int y;
static FinalFieldExample f;
public FinalFieldExample() {
x = 3;
y = 4;
}
static void writer() {
f = new FinalFieldExample();
}
static void reader(String name) {
if (f != null) {
int i = f.x;
int j = f.y;
if (i != 3 || j != 4) {
System.out.printf("reader %s sees it!%n", name);
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
就像之前我的类似主题一样 - 我尝试过使用Windows的不同PC(2到8个内核),甚至是我们服务器端的Solaris 32核心盒 - 我无法重现它:fx和fy - 总是已经很合适了-initialized.
对于Intel/x86/x64架构,我得到了答案 - 它们有很多默认的memery保证,可以防止这种构造函数逻辑重新排序.对Solaris/sparc来说似乎也是如此吗?
那么在哪些架构/操作系统中可以重现这种重新排序?
为了获得您想要的结果,您可能会尝试打开大量优化,因此在-server
模式下运行程序。
我首先想到的是制作f
volatile
,但这显然会搞砸整个实验。
打开即时编译器的 XML 日志记录(如果您使用的是 HotSpot JVM),并查看生成的机器代码(使用一些外部调试器或内存转储程序)。然后您可以检查生成的代码是否允许您观察您想要的结果。