Threads和println()语句之间的关系

时间:2015-12-16 12:05:43

标签: java multithreading

我尝试创建一些场景来演示跨线程共享变量时的可见性问题。我注意到在我测试的几乎所有情况下,如果在run()内部,我在使用共享变量的同一代码块中添加了System.out.println()语句,则无法生成可见性问题。我将举一个例子:

配置详细信息 - Oracle Java6 64位,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);
    }
    

    }

OUTPUT:线程一直无限运行

  • 2)没有可见性问题:

上面的相同代码,带有未完成的println()运行中的声明()

输出:

...

如果取消注释此行,代码将在没有可见性问题的情况下运行

如果取消注释此行,代码将在没有可见性问题的情况下运行

如果取消注释此行,代码将在没有可见性问题的情况下运行

X:19391

keepRunning是假的

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

2 个答案:

答案 0 :(得分:9)

PrintWriter已同步

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

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

简单来说,是的,调用System.out.println()可以实现此同步。

答案 1 :(得分:1)

此行为是特定于实现的。在OpenJDK中,println的正文已经同步,而API并未表明它是。