1

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

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

现在,当灯光状态变为“1”时,我的程序进入 if 语句并执行正常的代码。但这仅在进入 while 循环后有该打印输出语句时才有效。我觉得这很奇怪。'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;
}
4

2 回答 2

5

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

要解决此问题,您需要执行以下操作之一:

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

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

于 2012-11-25T17:17:28.717 回答
2

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

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

阅读更多:http: //javarevisited.blogspot.com/2011/06/volatile-keyword-java-example-tutorial.html#ixzz2DFw4l8AW

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

于 2012-11-25T17:21:35.597 回答