1

我遇到了一个非常奇怪的问题,Java 线程忙于等待。

我有一个线程忙于等待其他线程的静态变量的状态。假设忙等待的线程正在等待另一个线程的静态 int 变量达到某个值

while(OtherThread.countInt < 5);

如果我使用上面的代码,线程将被卡住,等待并且不会跳出 while 循环,即使static int countInt达到 5。

while(OtherThread.countInt < 5) {
    // waste some time doing meaningless work
}

但是,如果我使用这个其他代码,那么线程确实会脱离忙等待循环。有时,countInt一到5,其他时候稍等片刻。但它发生了。对于我的特定示例,我将其用作“无意义的工作”

print("busy waiting...",1000) // wasting time doing meaningless work

我定义printsynchronzied static void print(String s, int n)打印字符串s然后休眠n几毫秒。

是什么赋予了?为什么线程忙于等待第一个代码,而不是另一个?所有线程都有相同的优先级,所以它不能是一个优先级问题。

4

1 回答 1

3

countIntis not volatile,因此不能保证更改对等待线程可见。

由于您的print()方法synchronized可能会创建足够的内存屏障,因此更新的值对您的while循环可见。这本质上是一个巧合;while条件本身仍然被打破。这就是为什么正确设计和测试并发代码如此重要的原因——编写一些看起来只能按预期工作但稍后会失败的东西很容易(例如,在负载下、在不同的处理器上、在看似安全的重构之后等) .

使用适当的内存屏障,例如synchronised读写、volatile字段或跨线程通信机制,例如java.util.concurrent. 有许多相关的问题正在探索volatile和这些其他工具。

您还可以好好研究一下Java 的并发支持。跨线程通信很重要。

于 2016-11-27T23:34:47.493 回答