System.out.println行影响逻辑的执行

System.out.println Line Affecting Execution of the Logic

我已经运行陷入了一个难以置信的奇怪现象。我目前正在 Java 中编写一个即时消息程序,我有一个变量来表示新用户是否已连接(这是在单独的 class 中)。这是有问题的代码,其中对象 ListenerThread extends Thread :

boolean listenerThreadConnected = ServerDriver.getListenerThread().connected;
System.out.println("Whatever in here");
if(listenerThreadConnected){
    ...
    System.out.println("In the if statement");
    ...
}

所以,这段代码有效。当 listenerThreadConnected = true 执行 if 语句并输出 In the if statement 并执行 if 语句中的所有其他操作。但是,除了注释掉 System.out.println("Whatever in here")if 语句没有触发之外,我没有更改其他代码,也没有输出 In the if statement 的迹象。我的代码如下所示:

boolean listenerThreadConnected = ServerDriver.getListenerThread().connected;
//System.out.println("Whatever in here");
if(listenerThreadConnected){
    ...
    System.out.println("In the if statement");
    ...
}

我很困惑。这个 System.out.println 怎么会影响实际的逻辑呢?我知道这个问题很开放,但你有过类似的经历吗?对于某些上下文,这全部在 while 循环中,而 ListenerThread 是一个并发的 运行ning 线程。除了我当前的代码,我似乎无法复制这个结果。

[EDIT]Thread.sleep(1) 替换 System.out.println 似乎也有效,所以这让我认为这是一个并发问题。

一点也不奇怪,你肯定在多线程系统中并且你的应用程序正在获取过时的 boolean 值,你需要在读取变量 listenerThreadConnected 时确保内存可见性

如何:?

将此 boolean listenerThreadConnected 声明为易变的,错误必须消失!

请注意,System.out.println 通常实现为 synchronized(即使没有记录),以便您不会得到两个线程交错的输出。

执行该语句具有使变量更新对执行同步方法的线程可见的效果(这是一种 "happens before" 关系)。

通过删除 System.out.println 调用,您将删除此行为,因此您可能会看到过时的变量。

正如@Xoce웃Пepeúpa 所说,创建变量 volatile,或者做其他事情来确保内存可见性(例如将其更改为 AtomicBoolean)。