小编典典

线程与println()语句之间的关系

java

我试图创建一些方案来演示可见性问题,同时在线程之间共享变量。而且我注意到,在我测试的几乎所有情况下,如果在run()中我在使用共享变量的同一代码块中添加了System.out.println()语句,就不会产生可见性问题。我将提供一个示例:

配置详细信息-Oracle Java6 64bit,Eclipse Juno SR 2

  • 1)可见性问题:
        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);
    }


}

输出: 线程保持无限运行

  • 2)没有可见性问题:

上面相同的代码,在run()中使用未注释的println()声明

输出:

如果取消注释此行,则代码将正常工作而不会出现可见性问题

如果取消注释此行,则代码将正常工作而不会出现可见性问题

如果取消注释此行,则代码将正常工作而不会出现可见性问题

x:19391

keepRunning为假

由于我在所有尝试的示例中都注意到了类似的行为,因此我想知道是否在进行任何I / O操作之前是否由JVM进行了数据完整性检查。


阅读 210

收藏
2020-11-01

共1个答案

小编典典

PrintWriter已同步

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

System.out.println()主线程和第二线程中的两个顺序调用在两个线程之间创建同步顺序。这意味着在释放监视器(退出同步方法)之前在主线程中发生的所有操作(在您的情况下为变量更新)将由代码看到,并在获取监视器(输入同步方法)后在第二个线程中执行。

简单来说,是的,调用System.out.println()使此同步。

2020-11-01