在什么体系结构/操作系统中,其他线程可以在构造函数调用后看到默认的非最终字段值?
2022-09-04 04:56:23
我试图在非最终字段的对象初始化不足的情况下重现内存可见性问题(JLS 17.5 Final Field Semantics,FinalFieldExample类示例)。其中指出“但是,f.y不是最终的;相反,f.y不是最终的。因此,不能保证 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);
}
}
}
}
}
与之前的类似主题一样 - 我已经在Windows的不同PC(从2到8核)上尝试过,甚至在我们的服务器端Solaris 32核盒上 - 我无法重现它:f.x和f.y - 总是已经正确初始化。
对于我得到答案的英特尔/x86/x64 架构 - 它们几乎具有默认的 memery 保证,可防止此类构造函数逻辑重新排序。似乎 Solaris/sparc 也是如此?
那么,在什么体系结构/操作系统中可以再现这种重新排序呢?