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");
}
}
7
  • 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
    Commented May 23, 2023 at 6: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
    Commented May 23, 2023 at 6: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
    Commented May 23, 2023 at 6:41
  • 2
  • 1
    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
    Commented May 31, 2023 at 12:26

1 Answer 1

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.

Not the answer you're looking for? Browse other questions tagged or ask your own question.