IF语句只有在它正在测试的值的'sysout'之前才会执行

时间:2012-11-25 17:04:47

标签: java multithreading if-statement

我收到一个非常奇怪的错误。我有以下代码:

while (true) {
    System.out.println(model.getLightState());
    if (model.getLightState() == 1) {
        System.out.println("Entered..");
        view.driveThroughJunction();
        break;
    }
}

现在,当灯光状态变为“1”时,我的程序进入if语句并执行正常的代码。但是,如果我在输入while循环后输出了print out语句,那么这只能起作用。我觉得很奇怪。 'sysout'行会对if语句产生什么影响吗?显然它适用于上述情况。

为什么会这样?

编辑:

(in the model class)
public final byte getLightState() {
    return lightChanger.getLightValue();
}

(in lightchanger class)
public byte getLightValue() {
    return light.getState();
}

(in the light class)
public final byte getState() {
    return this.state;
}

2 个答案:

答案 0 :(得分:5)

您遇到同步问题,导致可见性问题。如果在读取和写入由多个线程共享的变量时未使用同步,则无法保证一个线程写入的值对其他线程可见。

要解决这个问题,你需要做其中一件事:

  • 制作state字段volatile
  • state字段类型更改为AtomicInteger
  • 同步对state字段的每次访问(使用synchronized关键字),当然每次都使用相同的锁。

您的sysout调用使值可见,因为它在内部调用一些方法将寄存器的状态刷新到主存储器(例如,通过写入volatile字段或调用synchronized方法)。

答案 1 :(得分:2)

您应该将模型实例声明为 volatile

Java中的Volatile用作Java编译器和Thread的指示符,它不缓存此变量的值并始终从主内存中读取它。因此,如果您希望通过实现共享任何读取和写入操作都是原子的变量,则应将它们声明为volatile变量。

了解详情:http://javarevisited.blogspot.com/2011/06/volatile-keyword-java-example-tutorial.html#ixzz2DFw4l8AW

从您的评论中可以看出,多个线程正在访问同一个模型实例并在同一个模型实例中执行读/写操作。如果没有 volatile 线程,则会缓存模型实例的值,从而最终导致脏读。发生System.out.println时,您的读/写操作会延迟一点(由于输出写入),因此线程能够从主存储器刷新缓存的值。