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

我试图创建一些场景来演示跨线程共享变量时的可见性问题。 我注意到在我测试的几乎所有情况下,如果在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); } 

    }

输出:线程保持无限运行

  • 2)没有可见性问题:

与上述相同的代码,带有未完成的println()运行中的语句()

OUTPUT:

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

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

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

X:19391

keepRunning是假的

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

PrintWriter已同步

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

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

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

此行为是特定于实现的。 在OpenJDK中, println的主体是同步的,尽管API没有声明它是。