Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Relationship between Threads and println() statements

I was trying to create a few scenarios to demonstrate visibility issues while sharing variable across threads. And I noticed that in almost all the cases I tested, if inside run() I added a System.out.println() statement in the same block of code where I am using the shared variable, the visibility issue is not producible. I will provide one example:

Configuration details - Oracle Java6 64bit, Eclipse Juno SR 2

  • 1)WITH VISIBILITY ISSUE:

    public class NoVisibility_Demonstration extends Thread {
    boolean keepRunning = true;
    public static void main(String[] args) throws InterruptedException {
        NoVisibility_Demonstration t = new NoVisibility_Demonstration();
        t.start();
        Thread.sleep(1000);
        t.keepRunning = false;
        System.out.println("keepRunning is false");
    }
    public void run() {
        int x = 1;
        while (keepRunning) 
        {
            //System.out.println("If you uncomment this line, the code will work without the visibility issue");
            x++;
    
        }
        System.out.println("x:"+x);
    }
    

    }

OUTPUT: The thread keeps running infinitely

  • 2) WITHOUT VISIBILITY ISSUE:

THE SAME CODE AS ABOVE, WITH THE UNCOMMENTED println() STATEMENT IN THE run()

OUTPUT:

...

If you uncomment this line, the code will work without the visibility issue

If you uncomment this line, the code will work without the visibility issue

If you uncomment this line, the code will work without the visibility issue

x:19391

keepRunning is false

Since I noticed similar behavior in all the examples I tried, I am wondering if there is any data integrity check by JVM before any I/O operation.

like image 972
Biman Tripathy Avatar asked Dec 16 '15 12:12

Biman Tripathy


2 Answers

PrintWriter is synchronized

public void println(String x) {
    synchronized(this) {
        this.print(x);
        this.newLine();
    }
}

Two sequential calls of System.out.println() in main thread and in second thread create a synchronization order between two threads. That means that all actions (in your case it is variable update), that happened in main thread before releasing a monitor (exiting synchronized method) will be seen by the code, executed in second thread after it acquires a monitor (enter synchronized method).

In simple words, yes, calling System.out.println() makes this synchronization.

like image 194
AdamSkywalker Avatar answered Nov 09 '22 23:11

AdamSkywalker


This behaviour is implementation specific. In OpenJDK, println's body is synchronized altough the API does not state that it is.

like image 29
Pétur Ingi Egilsson Avatar answered Nov 10 '22 00:11

Pétur Ingi Egilsson