0

一个使用线程的小程序真的让我很烦,有人能解释为什么这没有给出我认为应该的输出吗?

class FirstClass {
  public static void main(String args[]) {
    Class2 two = new Class2();
    Thread thread1 = new Thread(two);
    thread1.start();

    Class3 three =new Class3(two);
    Thread thread2 = new Thread(three);
    thread2.start();     
  }
}
class Class2 implements Runnable {
  public Boolean variable1 = false;
  @Override
  public void run() {
    System.out.println("Sleeping thread");
    try {
      Thread.sleep(3000);
    }catch(Exception e){}
    variable1=true;
    System.out.println("Variable 1 = " + variable1);
  }
}
class Class3 implements Runnable {
  Class2 two;
  public Class3(Class2 _two) {
    this.two = _two;
  }
  @Override
  public void run() {
    while(!this.two.variable1) {
      //System.out.println("in while");
    }
    System.out.println("Variable1 was changed to true"); 
  }
}

以上,会给我正确的输出,即“睡眠线程”、“变量 1 = 真”、“变量 1 已更改为真”。现在,如果我稍微更改程序并取消注释 'System.out.println("in while");' 我没有得到“Variable1 已更改为 true”,这就像它没有脱离 while 循环,但为什么 'System.out.println("in while")' 会使其中断?或者也许它不是吗?如果有人能解释发生了什么,我将不胜感激。

谢谢

4

1 回答 1

3

您在two.variable1没有任何同步的情况下从多个线程访问。所以你有一个可见性问题:第二个线程从其内部缓存中读取变量的值,并且不知道它已被第一个线程更改。

您应该创建变量volatile,或使用AtomicBoolean,或使用同步方法访问它,以确保对变量的写入刷新到主存储器并从主存储器读取变量。

由于 println 方法是同步的,因此调用System.out.println()具有使变量可见的副作用。

于 2013-03-09T11:19:51.563 回答