Java IF语句仅在其';s前面有一个';sysout';它所测试的价值

Java IF语句仅在其';s前面有一个';sysout';它所测试的价值,java,multithreading,if-statement,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 (true) {
    System.out.println(model.getLightState());
    if (model.getLightState() == 1) {
        System.out.println("Entered..");
        view.driveThroughJunction();
        break;
    }
}
现在,当灯光状态变为“1”时,我的程序会输入if语句,并执行代码。但这只有在进入while循环后有print-out语句时才有效。我觉得很奇怪。“sysout”行会对if语句产生任何影响吗?显然,对于上述情况是这样的

你知道为什么会这样吗

编辑:


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

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

  • 使
    状态
    字段
    可变
  • 状态
    字段类型更改为
    原子整数
  • 同步对
    状态
    字段的每次访问(使用
    synchronized
    关键字),当然每次都使用相同的锁

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

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

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

  • 使
    状态
    字段
    可变
  • 状态
    字段类型更改为
    原子整数
  • 同步对
    状态
    字段的每次访问(使用
    synchronized
    关键字),当然每次都使用相同的锁

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

您应该将模型实例声明为易失性

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

阅读更多:


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

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

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

阅读更多:


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

您是否在
getLightState
中更改任何内容?向我们展示您的
getLightState()
。您是否碰巧在一个单独的线程中运行此代码?能否尝试将模型实例声明为volatile?@anubhava成功了!请你提供一个答案并解释一下。谢谢。您是否在
getLightState
中更改了任何内容?向我们展示您的
getLightState()
。您是否碰巧在单独的线程中运行此代码?是否可以尝试将模型实例声明为volatile?@anubhava成功了!请你提供一个答案并解释一下。谢谢。使模型不稳定并不能解决问题——他正在访问另一个变量。如果它真的解决了问题,那纯粹是巧合。另一个答案是正确的。也许你能更好地解释这个纯粹的巧合理论。顺便说一句,另一个答案也建议使用volatile变量。使
model
volatile只会保证如果您编写
model=newmodel()它将被其他线程看到。它不能保证对其字段的更改是可见的。换句话说,它不能保证
model.state=someNewState将从另一个线程可见。另一个答案建议在
state
变量上使用volatile。使模型变为volatile并不能解决问题-他正在访问另一个变量。如果它真的解决了问题,那纯粹是巧合。另一个答案是正确的。也许你能更好地解释这个纯粹的巧合理论。顺便说一句,另一个答案也建议使用volatile变量。使
model
volatile只会保证如果您编写
model=newmodel()它将被其他线程看到。它不能保证对其字段的更改是可见的。换句话说,它不能保证
model.state=someNewState将从另一个线程可见。另一个答案建议在<代码上使用volatile
(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;
}