我找到了一段线程似乎饿死的代码 . 下面是一个简化的例子 . 这是饥饿的一个例子吗?线程没有终止的原因是什么?
注意:将睡眠状态更改为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 回答
您可能需要了解Java内存模型 . 多线程不仅仅是交织线程的动作;它是关于一个线程对另一个线程的动作的可见性 .
在这个问题的最底层是面对并发需要积极优化:任何确保线程之间内存一致性的机制都很昂贵,并且很多(大多数)数据不在线程之间共享 . 因此,未明确标记
volatile
或受锁保护的数据默认情况下被视为线程本地(当然没有严格保证) .在您的情况下,
finished
是一个这样的变量,如果它满足运行时,则允许将其视为线程局部变量 . 它确实令人高兴,因为循环可以重写为just
如果你在循环中做了任何重要的工作,它会表现得更好,因为不会不必要地重复读取
finished
,因此可能会破坏整个CPU缓存行 .上面的讨论应该足以回答你的直接问题,“这是饥饿”:循环没有完成的原因不是饥饿,而是无法看到其他线程的写入 .
那里's no starvation here, because you'没有做任何工作 . Starvation表示各种线程正在尝试访问相同的有限资源集 . 每个线程在这里尝试访问的资源是什么?他们挨饿了 .