2

我正在阅读 Java Concurrency in Practice 一书,这里是关于死锁的内容。

JVM不会从死锁中恢复,摆脱死锁的唯一方法是重新启动服务器。它还提到JVM使用图搜索,其中线程充当图节点,两个线程A和B之间的边被定义为线程A正在等待线程B已经持有的资源的锁定。这个图是有向的,如果有任何循环这个图,那么就有死锁

现在我的问题是,如果 JVM 知道存在死锁,那么它为什么不杀死一个线程并让其他线程继续执行呢?这背后是否有任何具体原因,或者我的问题本身是基于错误的结论?

请让我知道您对此的看法。提前致谢!!!

4

2 回答 2

7

现在我的问题是,如果 JVM 知道存在死锁,那么它为什么不杀死一个线程并让其他线程继续执行呢?这背后是否有任何具体原因,或者我的问题本身是基于错误的结论?

JVM 如何决定要杀死哪个线程?如果 JVM 在强制释放锁时允许无效数据进入某种关键数据库怎么办?

JVM 不能随意做出这类决定。它报告死锁,但不能自动从中恢复。

在使用锁修改两个关键对象但两个线程以不同顺序锁定它们的任何情况下,您都可以看到此问题。数据库事务能够从此类死锁中恢复,因为它们旨在回滚表和索引,但 Java 同步锁没有隐式内存回滚功能。通过杀死一个线程并释放它的锁,JVM 将允许传播部分内存更新。

于 2013-09-20T02:42:33.233 回答
4

杀死一个线程不会让另一个线程正常进行。事实上,杀死线程将是致命的。一个线程首先获得锁的原因是在该数据结构处于不一致状态时将其他线程排除在某个数据结构之外。在数据结构仍处于不一致状态的情况下释放锁将致命地污染进程上下文。

例如:

  1. 线程 A 锁定对象 1。

  2. 线程 B 锁定对象 2。

  3. 线程 A 将对象 1 置于不一致的状态。

  4. 线程 B 将对象 2 置于不一致的状态。

  5. 线程 A 在对象 2 上阻塞。

  6. 对象 1 上的线程 B 阻塞。

任何一个线程现在如何进行?每个线程都在等待另一个线程将对象返回到一致状态。

如果你不明白我所说的不一致状态是什么意思,这里有一个更清晰的例子。考虑这段代码:

  1. 获取保护foo和锁bar
  2. foo如果plusbar不是 10,则开始第三次世界大战。(不用担心,程序员仔细确保fooplusbar始终为 10,除非他真的必须开始第三次世界大战。)
  3. 增量foo
  4. 获取其他一些锁。
  5. 递减bar
  6. 释放另一个锁。
  7. 释放保护foo和的锁bar

如果在第 4 步出现死锁怎么办?您无法释放保护锁,foo并且bar运行此代码的下一个线程将引发第三次世界大战。显然,需要详细了解此特定代码的作用才能解开死锁。

于 2013-09-20T02:45:25.327 回答