Java - Happens before - volatile

happens-before, java, java-memory-model, multithreading

Solution

Update

Because you seem to want an explanation for the specific case of "2 3 2"

- X increments `i` (now 1)

- Y increments `i` (now 2)

- X reads `i` (X loads 2)

- Y reads `i` (Y loads 2)

- Y prints the value previously loaded (prints 2)

- Z increments `i`, reads `i`, prints `i` (prints 3)

- X prints the value previously loaded (prints 2)

The point is: `System.out.print(" " + count)` isn't atomic. The thread can be preempted after performing a volatile read and before printing the value.

If you want to prevent duplicate values from being printed, you have to perform the volatile read inside the lock:

public void increment() {
    int localCount;
    synchronized (lock) {
        count = count + 1;
        localCount = count; // volatile load
    }
    System.out.print(" " + localCount);
}

This wouldn't prevent values from being printed out of order though. In order to print them in order, without duplicates, you'd have to move the `print` into the lock as well.

Old Answer

The print statement is outside the lock. Consider the code running inside `System.out.print(" " + count)`.

- A thread X increments `i`

- Thread X evaluates the `print` arguments and performs a volatile read on the `count` variable, and loads the value `2`.

- Thread X is preempted by Thread Y, which increments `i`

- Thread Y loads `i` (which is now `3`), calls the print method which runs to completion.

- Thread Y is preempted, and Thread X now runs `print` to completion, which prints 2.

This would make the numbers show out of order, such as "3 2 4".

Some numbers might also be repeated when:

- Thread X increments `i` (which is now 2)

- Thread Y increments `i`(which is now 3)

- Thread X prints `i` (which is 3)

- Thread Y prints `i` (which is 3)

Problem

I have the below code ``` class VolatileCount { volatile int count; Object lock = new Object(); public void increment() { synchronized (lock) { count = count + 1; } System.out.print(" " + count); } } ``` If I call `increment()` on same object from multiple threads I get the below output (might be different on your machine) ``` 2 3 2 5 4 8 8 6 11 13 10 9 15 14 12 20 19 ``` Looking at the repeating numbers I think happens-before seems to be broken, because considering first three number (2 3 2), if a thread sees 3 , increment has happened and since the variable is volatile, its value should be 3 or more but cannot be 2 in any thread. However, the print line seems to have been reordered here, is it correct to reorder that line? What am I missing here? I run on JDK 7 (Eclipse)

Original source

Related problems