undefinedfix
Sign in

Analysis of visibility errors between threads in Java

walder edited in Thu, 26 Jan 2023

Title Description

In the verification of volatile keyword, we found this scenario: in the code, if the comment line is executed or not, the final result is different.

When the printed information is commented out, the business logic will be executed in a dead loop, which is understandable

When the comment is released, the business logic can read the value modified by the child thread

The source of the topic and my own ideas

Related codes

public class VolatileTest {

    public static void main(String[] args) {
        VolatileThread thread = new VolatileThread();
        thread.start();

        while (true) {
//            System.out.println("thread.isFlag():" + thread.isFlag());
            if (thread.isFlag()) {
                System.out.println("----------------------");
                break;
            }
        }
    }

    public static class VolatileThread extends Thread {

        public boolean flag = false;

        @Override
        public void run() {
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            flag = true;

            System.out.println("flag= " + flag);
        }

        public boolean isFlag() {
            return flag;
        }

        public void setFlag(boolean flag) {
            this.flag = flag;
        }
    }
}

What are your expectations? What is the actual error message?

Comment the result of South

image.png

Result of execution of South

2 Replies
user171780
commented on Thu, 26 Jan 2023

The main reason is implementation System.out.println Compared with other statements, it is very slow and involves a lot of internal operations, resulting in CPU cache failure. So the effect is equivalent to let the main thread finally have a chance to see the flag changed.

You can add count to compare (when I have output on my machine, I execute 70399 cycles, when I have no output, I execute 801053907 cycles).

In the end, we need to use the volatile keyword to deal with the visibility problem

        public  volatile boolean flag = false;
xsmb360ngay
commented on Thu, 26 Jan 2023

The essence of Sout is synchronous execution. You can see it by looking at the JDK source code, which is equivalent to partial synchronization in disguise.

To print, it is recommended to use log frames such as log4j and logback. You will find that the result is almost the same whether you annotate or not.