0

Question: Is this statement true: „A write to a volatile field happens-before every subsequent read of that or another volatile field.“

On How to understand happens-before consistent I found the following statements:

Happens-before: „Two actions can be ordered by a happens-before relationship. If one action happens-before another, then the first is visible to and ordered before the second.“

Volatile: „A write to a volatile field happens-before every subsequent read of that field.“

Visibility: „When Thread A changes/writes a volatile variable it also pushes all previous changes into RAM - Main Memory as a result all not volatile variable will be up to date and visible for another threads“.

In the following program, according to the java memory model, it is not guaranteed that the output "thread end" will appear on the console:

public class VolatileQuestion {

static boolean finish = false;

public static void main(String[] args) throws Exception {
    new Thread(() -> {
        while (!finish);
        System.out.println("thread end");
    }).start();
    Thread.sleep(2000);
    finish = true;
    System.out.println("main end");
}
}

Declaring field „finish" as volatile it is guaranteed that the output "thread end" will appear on the console:

public class VolatileQuestion {

static volatile boolean finish = false;

public static void main(String[] args) throws Exception {
    new Thread(() -> {
        while (!finish);
        System.out.println("thread end");
    }).start();
    Thread.sleep(2000);
    finish = true;
    System.out.println("main end");
}
}

In the third program, I don't declare field finish as volatile, but I introduce another field declared as volatile, which the main thread writes and the other thread reads. Therefore, according to the java memory model, the output of "thread end" is guaranteed:

public class VolatileQuestion {

static boolean finish = false;
static volatile boolean flush = false;

public static void main(String[] args) throws Exception {
    new Thread(() -> {
        while (!finish) {
            boolean dummy = flush;
        }
        System.out.println("thread end");
    }).start();
    Thread.sleep(2000);
    finish = true;
    flush = true;
    System.out.println("main end");
}
}

And now my question: What happens if I write a volatile field in the main thread and read another volatile field in the other thread: Is the output of "thread end" guaranteed in that case too?

public class VolatileQuestion {

static boolean finish = false;
static volatile boolean flush = false;
static volatile boolean refresh = false;

public static void main(String[] args) throws Exception {
    new Thread(() -> {
        while (!finish) {
            boolean dummy = refresh;
        }
        System.out.println("thread end");
    }).start();
    Thread.sleep(2000);
    finish = true;
    flush = true;
    System.out.println("main end");
}
}
luk2302
  • 55,258
  • 23
  • 97
  • 137
dibo
  • 1
  • The last snippet does not use refresh in any meaningful way. Nothing in the code depends on its value. It behaves exactly as the sniper before it. – luk2302 May 23 '23 at 06:22
  • The 4th version is equivalent to the 2nd one. The HB relation involving `finish` is the same. (The `flush` variable doesn't alter the HB relation for `finish`. It is just redundant.) And you can make a similar argument to say that the 4th version is equivalent to the 3rd version. – Stephen C May 23 '23 at 06:31
  • clearification: the reason for the instruction "boolean dummy = refresh;" is solely to refresh the cache of the thread. And my question is "Is it really refreshed"? If i replace the statement with "boolean dummy = flush;" the refresh is guaranteed! – dibo May 23 '23 at 06:41
  • Stephen: In the 3rd and 4th version finish ist not declared as volatile! – dibo May 23 '23 at 07:54
  • 2
    [4.5. Wishful Thinking: Unobserved Volatiles Have Memory Effects](https://shipilev.net/blog/2016/close-encounters-of-jmm-kind/#wishful-unobserved-volatiles) • [4.6. Wishful Thinking: Mismatched Ops Are Okay](https://shipilev.net/blog/2016/close-encounters-of-jmm-kind/#wishful-mismatched) – Holger May 23 '23 at 09:07
  • If a volatile read sees a particular volatile write then there is a happens-before relation between that write and that read. This makes it clear that it implies the same variable and this also makes clear that there is only a happens-before relation if that read sees that write. This also removes 'time' from the definition. Time can be very confusing with the JMM. – pveentjer May 31 '23 at 12:26
  • A correctly synchronized program in Java can only have sequential consistent executions. The real-time order doesn't need to be respected for sequential consistency. And this often leads to very hard-to-understand wording that gives the impression that the real-time order needs to be respected (especially when you see things like subsequent). – pveentjer May 31 '23 at 12:37

1 Answers1

0

What happens if I write a volatile field in the main thread and read another volatile field in the other thread

There are no guarantees in this case. Writing to a volatile field doesn't guarantee anything about any other variables. You get guarantees only by reading the same variable from a different thread.

In the fourth version of the code, the only thing tying the two threads together is finish, which is non-volatile and provides no guarantees.

Malt
  • 28,965
  • 9
  • 65
  • 105