这是饥饿吗?

我找到了一段线程似乎饿死的代码。 下面是一个简化的例子。 这是饥饿的一个例子吗? 线程没有终止的原因是什么?

注意:将睡眠更改为1有时会导致终止。 注释掉的Thread.yield()可以解决问题(对我而言)。

public class Foo { public static boolean finished = false; public static void main(String[] args) { Runnable worker = new Runnable() { @Override public void run() { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } finished = true; } }; new Thread(worker).start(); while (!finished) { // Thread.yield(); } } } 

您可能需要了解Java内存模型。 multithreading不只是交错线程的动作; 它是关于一个线程对另一个线程的操作的可见性

在这个问题的最底层是面对并发需要积极的优化:任何确保线程之间内存一致性的机制都是昂贵的,并且很多(大多数)数据不在线程之间共享。 因此,未明确标记为volatile或受锁保护的数据默认情况下被视为线程局部 (当然,没有严格的保证)。

在你的情况下, finished是这样一个变量,如果它满足运行时的话,它允许被视为线程局部的。 它确实令人高兴,因为

 while (!finished); 

循环可以重写为just

 if (!finished) while (true); 

如果你在循环中做了任何重要的工作,它会执行得更好,因为读取finished不会不必要地重复,因此可能会破坏整个CPU缓存行。

上面的讨论应该足以回答你的直接问题,“这是饥饿”:循环没有完成的原因不是饥饿,而是无法看到其他线程的写入。

这里没有饥饿,因为你没有做任何工作。 饥饿意味着各种线程试图访问相同的,有限的资源集。 每个线程在这里尝试访问的资源是什么? 他们没有“吃”任何东西,所以他们不能饿死。