javavolatilejlshappens-before

Does the semantics of java volatile guarantee that wrong results will not appear? (Two threads write first and then read)


volatile x=y=0

Thread1
x=1
r1=y

Thread2
y=1
r2=x

r1 and r2 are local variables

Question1:

Is the result of r1==r2==0 illegal and does not appear?

All statements are writing or reading volatile fields, which should be one of the three cases of r1==1 or r2==1 or r1==r2==1 according to common sense.

What confuses me is that the semantics of volatile is that when read sees the result of write, the happens-before rule is established. In this test, if two threads cannot see each other's results, it does not violate the rules of happens-before (update: this is wrong).

JLS says happens-before rules is not enough, And there is a Causality Test Cases. I understand it as some supplementary special case rules, but i didn't find the case for this question in those exception rules.


Solution

  • Causality is needed for OOTA problems.

    So imagine the following code:

    int a=0,b=0 (non volatile!)
    
    thread1:
        r1=a
        b=r1
    
    thread2:
        r2=b
        b=42
    

    Is r1==r2==42 an allowed execution? Yes, because x,y are not volatile, the reads can see values they are racing with. This is in line with the definition of happens-before consistent:

    If you have data races, you can get executions that are not sequential consistent.

    If we modify the example slightly:

    int a=0,b=0 (non volatile!)
    
    thread1:
        r1=a (1)
        b=r1 (2)
    
    thread2:
        r2=b (3)
        b=r2 (4)
    

    Can we get 'r1==r2==42'? Let's assume we have some magical CPU that speculates that b=42 at (3):

    So we get:

    speculate b=42
    r2=42 (3)
    b=42 (4)
    r1=42 (1)
    b=42 (2)
    

    The speculation of the CPU has paid off because the speculation of b=42 was correct!

    The value 42 appeared out of thin air and it is forbidden by the JMM. To resolve this problem, every execution needs to have some causal order so that causal loops are prevented.

    About question 1:

    Is the result of r1==r2==0 illegal and does not appear?

    Yes, it is illegal. Since every variable is volatile, there are no data races and therefore only sequential consistent executions are allowed.

    Your issue is that you are not seeing that the program order needs to be preserved within a sequential consistent execution.

    volatile x=y=0
    
    Thread1
    x=1    (1)
    r1=y   (2)
    
    Thread2
    y=1    (3)
    r2=x   (4)
    

    (1) happens before (2) due to program order.

    (3) happens before (4) due to program order.

    In the JMM the happens-before relation is defined as the transitive closure of the union of the program order and the synchronizes-with order.