2010-10-28 56 views
14

在高度并发的系统中,可能很难确信您的锁的使用是正确的。具体而言,如果在另一个线程中以正确的顺序获取锁而获取的顺序不是预期的顺序,则会导致死锁。在Java中声明同步的顺序

有一些工具(例如Coverity)可以在代码库上进行静态分析并寻找“异常”的锁定顺序。我想探索其他选择来满足我的需求。

是否有任何轻量级*工具可用于检测Java代码,这些工具可以检测到以预期以外的顺序获取锁的情况?我可以通过注释/注释显式调用锁定命令。

首选免费和/或开源解决方案。请同时评论这个问题是否存在非仪器方法。

*对于我而言,重量轻是指...

  • 如果是仪表,我仍然可以使用相同的球场性能运行我的程序。我想,30-50%的降解是可以接受的。
  • 我不必花半天的时间与工具进行交互,只是为了获得“好的”。理想情况下,我应该只注意到在出现问题时我正在使用它。
  • 如果是仪表,应该很容易在生产环境中禁用。
  • 它不应该在每个synchronize声明中混淆我的代码。如前所述,我可以明确地评论/注释被相对排序锁定的对象或类的对象。
+1

...这就是为什么Actor模型和STM越来越流行 – 2010-10-28 20:32:34

+0

有人有一个引用java.lang.Thread.holdsLock(Object)的响应被及时删除。我无法自己找到这种方法,谢谢你的指点。不过,我的问题依然存在。 – 2010-10-28 20:48:37

+0

你有没有发现任何像样的事情?我在C++中有非常复杂的死锁检测代码,在我的情况下,我想用我们的Java代码来捕获在C++和/或java端的锁可能会相互干扰并导致死锁的情况。 – Pavel 2015-01-27 02:32:35

回答

3

我还没有使用过AspectJ,因此无法证明它使用起来有多容易。我用ASM来创建一个自定义的代码分析器,这是大约2天的工作。仪器同步的努力应该类似。 AspectJ应该更快,更容易,一旦你加快了方面。

我已经为我们基于C++的服务器实现了死锁检测跟踪。这是我如何做的:

  • 当曾经获得或释放锁我跟踪:
    • <time> <tid> <lockid> <acquiring|releasing> <location in code>
  • 这额外的跟踪性能的影响非常显着,是不是在生产中使用。
  • 因此,当在生产中发现可能的死锁时,我使用日志文件找出死锁周围发生的事情。然后在打开跟踪的情况下在测试环境中再现此功能。
  • 然后我在日志文件上运行了一个脚本来查看死锁是否可行以及如何。我用awk脚本,使用这种algoritm:
    • FOREACH线
      • 如果获取
        • 添加lockid到当前锁的列表此线程
        • 在此列表中添加每对锁的一组为此线程锁定对。例如用于Lock A -> Lock B -> Lock C列表生成对(Lock A, Lock B), (Lock A, Lock C), (Lock B, Lock C)
      • 只要解除
        • 从列表的尾部删除当前lockid该线程
    • 对于每个锁对搜索所有其他线程的反向锁对,每个匹配是一个潜在的死锁,因此打印受影响的线对和线程
    • 而不是让算法更聪明我然后桌子检查,第锁定获取以查看它是否是真正的死锁。

我没有找到多天的僵局的原因后这样做,花了几天时间来实施并在几个小时找到了僵局。

如果你正在考虑在Java的东西,这个办法要考虑的是:

  • 你只使用​​,保护重要的部分?你在使用java.lang.concurrent中的类吗? (这些可能需要特殊处理/仪器)
  • 使用aspect/ASM打印代码位置有多容易?我在C++中使用了__FILE____LINE__。 ASM会给你类名,方法名和签名。
  • 您无法检测用于保护跟踪/记录的锁。
  • 如果您使用每个线程的日志文件和文件对象的线程本地存储,则可以简化您的检测。
  • 你如何唯一标识你同步的对象?也许toString()和System.identityHashCode()就足够了,但可能需要更多。我用C++中的对象地址。
+0

这是一个合理的解决方案,但我希望有一个工具可以为我完成所有这些工作。将更多地考虑ASM - 谢谢。 – 2010-10-29 13:08:56

0

没有得到你一路有,但一个良好的开端是使用JCIP annotations,并FindBugs抓住一些东西。

+0

除非我遗漏了一些东西,FindBugs没有对显示器(同步块)排序进行任何检查。 – 2010-10-29 13:01:51

+0

@德里克·赖斯:我没有意识到有任何工具可以完成OQ所要求的工作,但在附近提供了一些东西...... – andersoj 2010-10-29 16:17:05

1

您可以使用AspectJ,这是相对容易学习,并允许您设置自己的自定义和简化的方式来监视您的线程和他们访问的任何锁。

+1

谢谢。我遵循这个想法,直到我得到这篇文章“AspectJ中同步块的加入点”:http://www.cs.man.ac.uk/~xic/SBJP_AspectJ.pdf – 2010-10-29 12:55:55

+0

不错的论文。感谢分享链接,如果这些缺点不能在您的情况下使用,感谢抱歉。 – 2010-10-31 01:26:42