两个相关volatile变量的内存可见性语义

时间:2014-06-29 08:17:13

标签: java memory volatile jls java-memory-model

考虑JLS section on volatile fields

中的以下程序
class Test {
    static volatile int i = 0, j = 0;
    static void one() { i++; j++; }
    static void two() {
        System.out.println("i=" + i + " j=" + j);
    }
}

考虑两个线程同时执行方法one()two()

JLS声明如下:

  

这允许方法一和方法二同时执行,但是   保证访问i和j的共享值   与它们出现的次数完全相同,顺序完全相同   在每个线程执行程序文本期间发生。   因此,j的共享值永远不会大于i的共享值,   因为对i的每次更新都必须反映在i的共享值中   在更新到j之前发生。但是,任何给定的都是可能的   方法二的调用可能会观察到j的值很多   大于i观察到的值,因为方法一可能是   在方法二取出之间执行多次   i的值和方法二取值j的时刻。

我对上面的引文感到很困惑,因为它说了两个相互矛盾的陈述:

  1. j的共享值从不大于i的共享值。 (强调我的)。

  2. j的值远远超过i观察到的值。

  3. 第一个语句对我有意义,因为如果我们将程序顺序规则(i++之前发生的j++)与volatile的内存可见性保证(之前发生)相结合,我可以理解为什么j的值不能超过i。但我无法看到j的价值如何远远超过i

    请你帮我理解这部分。

1 个答案:

答案 0 :(得分:3)

在任何给定时刻,j的实际值绝不会大于i的实际值。但是当声明

System.out.println("i=" + i + " j=" + j);

已执行,ij未在同一时间进行评估。在j之后评估i。评估i时,j小于或等于i。但是,在评估j时,另一个线程可能多次调用方法one(),因此ij可能会多次递增。因此j仍为<= i,但打印的内容可能是

i=4 j=257

因为它实际上是

at time t0, i=4
at time t1, j=257