简体   繁体   中英

Memory visibility semantics of two related volatile variables

Consider the following program from the 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);
    }
}

Consider two thread are concurrently executing method one() and two() .

JLS states the following:

This allows method one and method two to be executed concurrently, but guarantees that accesses to the shared values for i and j occur exactly as many times, and in exactly the same order, as they appear to occur during execution of the program text by each thread. Therefore, the shared value for j is never greater than that for i, because each update to i must be reflected in the shared value for i before the update to j occurs. It is possible, however, that any given invocation of method two might observe a value for j that is much greater than the value observed for i, because method one might be executed many times between the moment when method two fetches the value of i and the moment when method two fetches the value of j.

I am really confused by the above citation because it says two contradictory statements:

  1. The shared value for j is never greater than that for i . (emphasis mine).

  2. Value for j that is much greater than the value observed for i .

The first statement makes sense to me because if we combine the program order rule( i++ happening before j++ ) and the memory visibility guarantee of volatile (happens-before) I can sort of see why the value of j can't exceed i . But I an unable to see how the value of j can can far exceed i .

Can you please help me understand this part.

The actual value of j can never be greater than the actual value of i at any given moment. But when the statement

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

is executed, i and j are not evaluated at the same moment. j is evaluated after i is. When i is evaluated, j is smaller or equal to i . But by the time j is evaluated, the other thread might have called the method one() many times, and both i and j might thus have been incremented many times. So j is still <= i , but what is printed could be

i=4 j=257

because it is in fact

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM