考虑一个简单的单线程Java程序执行,不涉及同步操作,只是实例变量的简单读写。简单地忽略所有写入的实现似乎符合Java内存规范。首先,来自§17.4的适用的一般声明:
内存模型确定程序中每个点可以读取的值。隔离中每个线程的操作必须表现为受该线程语义的控制,但每次读取所看到的值都由内存模型决定。
相关的限制因素如下(§17.4.5):
如果x和y是同一个线程的动作,并且x在程序顺序中位于y之前,那么hb(x,y)。
一组动作A发生 - 在一致之前如果对于A中的所有读取r,其中W(r)是r看到的写入动作,则不是hb(r,W(r))的情况或者在A中存在写w,使得wv = rv和hb(W(r),w)和hb(w,r)。
这基本上排除了发生之前它所观察到的写入。另一个条款只是一个完整性条款,它阻止某些v
看到之前写的那个v
,同时又写了同一个v
。
我无法保证能够正确地观察到写入,只能对可能无法观察到的写入进行限制。
我在这里缺少什么? JVM是否真的可以省略这样一个微不足道的保证?
答案 0 :(得分:3)
让我们使用:
class MyClass {
private static int i = 0;
public static void main(String[] args) {
i = 3; //w
System.out.println(i); //r
}
}
当程序包含两个冲突的访问(第17.4.1节)时,这些访问不是由先发生关系排序的,而是说它包含数据争用。
您的程序是单线程的 =>我们从程序顺序约束中得到hb(w,r) =>它是正确同步的 =>程序的所有执行似乎都是顺序一致的 =>它将打印3