我正在尝试在无限while循环内运行for循环。没有打印语句时,代码未按预期运行,但有打印语句时,代码运行正常。这是代码:
class Test implements Runnable{
public static int varint = 0;
public static void main(String args[]){
Thread x = new Thread(new Test());
int i;
x.start();
while(true){
System.out.println("Hello World"); //If this isn't included,
//the exit statement isn't executed
for(i=0;i<varint;i++){
System.out.println("Exit");
System.exit(0);
}
}
}
public void run(){
try{
Thread.sleep(5000);
} catch(Exception e){
System.out.println("Caught");
}
varint = 1;
}
}
这只是一个更大循环中的一个小例子。我该如何解决?
答案 0 :(得分:7)
您有一场数据竞赛。其中一个线程写入varint
,另一个线程读取varint
,没有显式同步。 varint
未声明为易失性。根据Java内存模型,不能保证读取线程会看到varint
已被更改。
当您添加println
时它起作用,因为println在内部使用同步,这使varint
对正在运行的线程可见。
要么使用锁定来读取/写入varint
,要么将其声明为volatile
。
这是Java内存模型和volatile的良好来源:
http://tutorials.jenkov.com/java-concurrency/java-memory-model.html#visibility-of-shared-objects
答案 1 :(得分:1)
不能保证在此头像中执行循环的主线程看到对varint
的任何更新。因此varint
可以更新为1或100,但是仍然不能保证主线程能够看到更新。
为了保证内存可见性,请使用易失性或同步原语。
请see the following link来自Java 5 Concurrency的架构师。本文解释:“状态标志和易失性”
另一方面,在某些情况下(如您添加打印件时的情况),读取线程可能会看到更新,并且似乎程序运行正常。这类可见性问题很难投入生产。