Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Java memory model during context switches

Recently in a conference talk the following was used as an example to demonstrate the Java memory model in a multithreaded environment.

public class A {

    public static boolean done;

    public static void main(String[] args) throws InterruptedException {
        done = false;
        new Thread(new Runnable(){
            public void run() {
                System.out.println("running...");

                int count = 0;
                while (!done) {
                    count++;
                }

                System.out.println("Exiting thread");
            }
        }).start();

        System.out.println("in main...");
        Thread.sleep(2000);

        System.out.println("setting done to true");
        done = true;
    }
}

I understand that the new thread created in above code will never exit because of done variable being cached in Thread's local cache. And a proper solution will be to make the done variable volatile.

But if inside the while loop, we call Thread.sleep() as follows

    while (!done) {
        count++;
        try {Thread.sleep(0);} catch(Exception e){}
    }

then the Thread successfully exits.

My understanding is that because of sleep(0) a context switch will occur that will invalidate the cache entries, so each time the updated value of done is retrieved. Is my understanding correct? Also is this behaviour dependent on the number of cores of the machine?

like image 224
JavaLearner Avatar asked Apr 03 '21 17:04

JavaLearner


People also ask

What do you understand by Java memory model?

The Java memory model describes how threads in the Java programming language interact through memory. Together with the description of single-threaded execution of code, the memory model provides the semantics of the Java programming language.

How does JVM manage memory?

JVM Memory Structure. JVM creates various run time data areas in a heap. These areas are used during the program execution. The memory areas are destroyed when JVM exits, whereas the data areas are destroyed when the thread exits.

What is the memory model for threads?

The memory model stipulates that changes to the values of shared variables only need to be made visible to other threads when such a synchronization barrier is reached. Moreover, the entire notion of a race condition is defined over the order of operations with respect to these memory barriers.

What are the key memory segments inside JVM?

The following are key memory segments inside a JVM: Program Counter (PC) Register. Method Area. Heap.


1 Answers

Java Language Specification clearly states that Thread::sleep does not have any happens-before semantics (and those are the only one you want to reason with):

... Thread.sleep nor Thread.yield have any synchronization semantics...

As such whatever output you "happen" to see using it, are not guaranteed by the specification. The only guarantees you have is when done is volatile, again, because the JLS gives you such guarantees.

Your reasoning about a correctly synchronized program must be backed against happens-before, context switch, caches, etc. are irrelevant.

like image 86
Eugene Avatar answered Oct 13 '22 21:10

Eugene