我遇到了一个令人难以置信的奇怪现象。我目前正在使用Java编写一个即时消息程序,我有一个变量来表示新用户是否已连接(这是在一个单独的类中)。以下是对象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是一个并发运行的Thread。除了我当前的代码之外,我似乎无法复制此结果。
[编辑] 用System.out.println
替换Thread.sleep(1)
似乎也有效,所以这让我觉得这是一个并发问题。
答案 0 :(得分:4)
根本不是那么多,您肯定在多线程系统中并且您的应用程序获得了过时的boolean
值,您需要在读取变量 listenerThreadConnected 时确保内存可见性
如何:吗
将此boolean listenerThreadConnected
声明为volatile,错误必须消失!
答案 1 :(得分:2)
请注意,System.out.println
通常实现为synchronized
(即使没有记录),以便您不会将两个线程的输出交错。
执行该语句的效果是对执行同步方法的线程可见的变量进行更新(这是“之前发生的”关系)。
删除System.out.println
调用会删除此行为,因此您可能会看到过时的变量。
正如@Xoce웃Пepeúpa所说,制作变量volatile
,或做其他事情以确保内存可见性(例如将其更改为AtomicBoolean
)。