我试图创建一些方案来演示可见性问题,同时在线程之间共享变量。而且我注意到,在我测试的几乎所有情况下,如果在run()中我在使用共享变量的同一代码块中添加了System.out.println()语句,就不会产生可见性问题。我将提供一个示例:
配置详细信息-Oracle Java6 64bit,Eclipse Juno SR 2
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); } }
输出: 线程保持无限运行
上面相同的代码,在run()中使用未注释的println()声明
输出:
…
如果取消注释此行,则代码将正常工作而不会出现可见性问题
x:19391
keepRunning为假
由于我在所有尝试的示例中都注意到了类似的行为,因此我想知道是否在进行任何I / O操作之前是否由JVM进行了数据完整性检查。
PrintWriter已同步
public void println(String x) { synchronized(this) { this.print(x); this.newLine(); } }
System.out.println()主线程和第二线程中的两个顺序调用在两个线程之间创建同步顺序。这意味着在释放监视器(退出同步方法)之前在主线程中发生的所有操作(在您的情况下为变量更新)将由代码看到,并在获取监视器(输入同步方法)后在第二个线程中执行。
System.out.println()
简单来说,是的,调用System.out.println()使此同步。