我收到一个非常奇怪的错误。我有以下代码:
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;
}
答案 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
时,您的读/写操作会延迟一点(由于输出写入),因此线程能够从主存储器刷新缓存的值。