这是饥饿吗?

时间:2014-01-21 20:09:33

标签: java multithreading

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

注意:将睡眠状态更改为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();
        }
    }
}

2 个答案:

答案 0 :(得分:8)

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

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

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

while (!finished);

循环可以重写为

if (!finished) while (true);

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

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

答案 1 :(得分:0)

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