我试图创建一些场景,以展示在跨线程共享变量时的可见性问题。我注意到,在我测试的几乎所有情况下,如果我在run()内部添加一个System.out.println()语句,并且在使用共享变量的代码块中,可见性问题就不会出现。我提供一个例子:
配置细节 - Oracle Java6 64位,Eclipse Juno SR 2
1)WITH VISIBILITY ISSUE:
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 为 false
由于我在尝试的所有示例中都发现了类似的行为,因此我想知道 JVM 是否在任何 I/O 操作之前进行数据完整性检查。
while
循环中使用System.out.println()
会显著影响每次循环迭代完成所需的时间。向控制台输出信息是慢的,而简单地增加一个int
变量非常快速。这只是需要记住的一些事情。 - JonK