Java死锁:是否存在不是bug的情况?

Java死锁:是否存在不是bug的情况?,java,tomcat,lucene,deadlock,Java,Tomcat,Lucene,Deadlock,我对一个Java程序进行了线程转储,它说发现了一个Java级死锁 我能自信地确认这个程序中有一个bug吗 对我来说,这听起来像是一个编程问题,唯一的解决办法是修复源代码。 我错了吗?在某些情况下,死锁是程序执行的正常部分,死锁最终会以某种方式消失吗 它是一个相当传统的Java web应用程序,拥有数百名用户。两个互相等待的线程似乎是一个请求工作线程和一个索引作业,都使用sun.misc.Unsafe.park。据我所知,该程序没有任何线程监控元复杂性 在某些情况下,死锁是程序执行的正常部分,死锁

我对一个Java程序进行了线程转储,它说
发现了一个Java级死锁

我能自信地确认这个程序中有一个bug吗

对我来说,这听起来像是一个编程问题,唯一的解决办法是修复源代码。
我错了吗?在某些情况下,死锁是程序执行的正常部分,死锁最终会以某种方式消失吗

它是一个相当传统的Java web应用程序,拥有数百名用户。两个互相等待的线程似乎是一个请求工作线程和一个索引作业,都使用
sun.misc.Unsafe.park
。据我所知,该程序没有任何线程监控元复杂性

在某些情况下,死锁是程序执行的正常部分,死锁最终会以某种方式消失吗

理论上是的,这取决于死锁的类型

例如,如果两个线程是
Object.wait()
死锁的,那么其中一个wait调用可能会超时(最终)。或者,第三个线程可以通过在其中一个死锁线程上调用
thread.interrupt()
来打破死锁。这可能是一种故意打破僵局的策略,或者出于其他原因

另一方面,原始互斥体上的死锁永远不会自动消失,除非调用一个不推荐使用的线程停止/杀死方法,否则死锁是无法打破的。如果这样做,可能会使数据结构处于中间状态,从而导致在打破锁后继续存在问题


要寻找的关键是阻塞动作是否可中断;e、 g.是否可以抛出
中断异常
或类似异常

在某些情况下,死锁是程序执行的正常部分,死锁最终会以某种方式消失吗

理论上是的,这取决于死锁的类型

例如,如果两个线程是
Object.wait()
死锁的,那么其中一个wait调用可能会超时(最终)。或者,第三个线程可以通过在其中一个死锁线程上调用
thread.interrupt()
来打破死锁。这可能是一种故意打破僵局的策略,或者出于其他原因

另一方面,原始互斥体上的死锁永远不会自动消失,除非调用一个不推荐使用的线程停止/杀死方法,否则死锁是无法打破的。如果这样做,可能会使数据结构处于中间状态,从而导致在打破锁后继续存在问题



要寻找的关键是阻塞动作是否可中断;e、 g.它是否可以抛出一个
中断异常
或类似的异常。

它有点像一个异常(尽管这是一个非常恶心和丑陋的异常:):如果您准备处理死锁,因为死锁可能发生在您的应用程序中(例如,您正在用java编写DB服务器),那么死锁就没有问题


也就是说,在大多数情况下,它实际上是一个bug,比如未经检查的异常,可怕的NPE:(

它有点像一个异常(尽管这是一个非常恶心和丑陋的异常:):如果您准备处理死锁,因为它们可能发生在您的应用程序中(例如,您正在用java编写DB服务器)那他们就没问题了


也就是说,在大多数情况下,它实际上是一个bug,比如未经检查的异常,可怕的NPE:(

+1我很想知道这件事。我听说的每一个死锁案例都是一个bug,但可能有一个例子不是这样的。+1我很想知道这件事。我听说的每一个死锁案例都是一个bug,但可能有一个例子不是这样的。我认为如果你使用一个超时的操作(
Object.wait
像各种更高级别的构造一样具有重载),那么它就不是死锁,因为至少有一个操作不仅依赖于另一个操作来完成(它正在等待该操作或等待超时)。@yshavit-你可以这么说,但是如果故意将超时设置为一个巨大的值,例如
Thread.sleep会怎么样(Integer.MAX_VALUE)
旨在创建一个不会超时的可中断等待。问题是,无论这是否是“死锁”,效果都是一样的根据你的定义。那么它就不会是死锁,但它仍然是一个坏错误——一个有效的死锁,你可以称之为,但不是一个真正的死锁。但问题不是“在技术上不是死锁,但实际上是相似的,总是错误”,这可能是一个更棘手的问题(有多接近就足够了?)。我想不出在任何情况下,真正的死锁——不会释放循环依赖的资源——只不过是生产中的一个bug。(我可以想象一个懒散编写的测试创建死锁,以在第三个测试中证明死锁的线程挂起。)@伊莎维特-让我直截了当地说。我想你是在吹毛求疵。除非OP插话说他只对符合你对僵局定义的僵局感兴趣,否则你所做的细微区分与问题无关。@伊莎维特,斯蒂芬:很抱歉没有精确。让我们假设僵局是一种看起来像
在使用KILL-3在HotSpot上运行Java线程转储时发现了一个Java级死锁
。我认为,如果您使用超时的操作(
Object.wait
和各种更高级别的构造一样有这样的重载),那么它就不是死锁,因为至少有一个操作不仅依赖于另一个操作来完成(它正在等待那个或等待一个超时)。@yshavit-你可以这么说,但是如果故意将超时设置为一个很大的值,例如
Thread.sleep(Integer.MAX_value)
和t