如何使用NetBeans删除Java代码中的死锁

use*_*247 3 java multithreading deadlock

我在Java中有旧的代码死锁...我从未使用netbeans作为开发工具......但是,我需要修复代码.

我在调试模式下运行应用程序,单击检查死锁并且netBeans带来了一个屏幕.四个线程中有两个是红色的...请参阅下面的屏幕转储.

我是多线程的新手,并且代码顶部不是我的......

什么最有可能导致问题?

替代文字

小智 5

据我所知,问题很可能与多线程获取和释放锁的方式(或更具体地说,顺序)有关.在上面的示例中,两个线程需要访问两个锁(或监视器):

  • nano.toolbox.strategies.ESMarketMaker
  • nano.toolbox.strategies.ExecutionManager

从当前处于死锁的两个线程的堆栈跟踪中,我们可以看到线程'ExecutionManager'已经获得了ExecutionManager监视器,但正在等待'ESMarketMaker'监视器的获取(同时仍然持有'ExecutionManager'监视器).

另一方面,'StrategyManager'线程已经获得了'ESMarketMaker'监视器,但正在等待'ExecutionManager'监视器的采集(同时仍然持有'ESMarketMaker'监视器).

这是死锁的一个类示例,以及锁的获取顺序可能导致死锁的多种方式.

有很多方法可以解决这些问题:

  • 如果可能,所有需要一些锁操作的线程必须以相同的顺序获取共享锁(反向顺序是上述死锁中的问题).但这并不总是可能的,因为多个线程在不同条件下可能只有半重叠锁使用,为什么设计一个可确保统一排序的采集协议可能很困难或不可能.
  • 您也可以使用tryLock(),这是一种非阻塞采集,它返回一个标志来指示成功或失败,并为您提供在重新尝试之前执行其他操作的选项.在这种情况下,我建议的一件事是,如果获取失败,则删除所有当前拥有的锁并再次从头开始尝试(因此让位于当前线程持有的任何或所有锁上的任何人都可以完成工作,也许释放此线程重试时所需的锁定).

有一点需要注意的是,有时在决定使用协议时,您需要更加明确地控制锁,而不是Java中的正常同步.在这些情况下,显式ReentrantLock实例的使用可能是一个好处,因为这些允许您执行诸如检查锁是解锁还是当前锁定之类的操作,并执行如上所述的非阻塞尝试锁.

我希望这有帮助,对不起,我不能更具体,但我需要看到源代码.:-)

(哦,ps,第三件事可能会选择,如果死锁是必须通过所有成本避免的事情,是调查建模工具,在程序状态和锁定模型状态机,可以使用与分析工具一起使用,可以检查此类模型中是否存在可能的死锁,如果找到任何此类模型,则会给出示例).

  • +1 ......但我不同意释放锁定并重新获取它们的部分.如果两个代理执行相同的操作,那么他们可能会遇到活锁.基本上,两个代理不断获取第一个锁,无法获得第二个锁,释放第一个锁并持续重复该过程. (2认同)