Java中同步顺序的断言
在高度并发的系统中,很难确信锁的使用是正确的。具体地说,如果在另一个线程中以正确的顺序获取锁时,以预期的顺序获取锁,则可能会导致死锁 有一些工具(例如Coverity)可以对代码库进行静态分析,并查找“异常”的锁定顺序。我想探索其他方法来满足我的需求 是否有任何轻量级的*工具用于检测Java代码,这些工具可以检测以非预期顺序获取锁的情况?我可以通过注释/注释显式地调用锁定命令 首选免费和/或开源解决方案。如果存在解决此问题的非仪器化方法,也请发表意见 *就我而言,轻量化意味着Java中同步顺序的断言,java,concurrency,synchronization,instrumentation,Java,Concurrency,Synchronization,Instrumentation,在高度并发的系统中,很难确信锁的使用是正确的。具体地说,如果在另一个线程中以正确的顺序获取锁时,以预期的顺序获取锁,则可能会导致死锁 有一些工具(例如Coverity)可以对代码库进行静态分析,并查找“异常”的锁定顺序。我想探索其他方法来满足我的需求 是否有任何轻量级的*工具用于检测Java代码,这些工具可以检测以非预期顺序获取锁的情况?我可以通过注释/注释显式地调用锁定命令 首选免费和/或开源解决方案。如果存在解决此问题的非仪器化方法,也请发表意见 *就我而言,轻量化意味着 如果是指令插入,
- 如果是指令插入,我仍然可以以大致相同的性能运行我的程序。我想30-50%的降解是可以接受的
- 我不必花半天的时间与这个工具交互,只为了得到一个“好”的结果。理想情况下,我应该只在出现问题时才注意到我正在使用它
- 如果是检测,那么在生产环境中应该很容易禁用它
- 它不应该在每个
语句中都使我的代码混乱。如前所述,我可以显式注释/注释被相对顺序锁定的对象或对象类synchronize
- 在获取或释放锁时,我跟踪到:
- 这个额外的跟踪极大地影响了性能,在生产中不可用
- 因此,当在生产中发现可能的死锁时,我使用日志文件来了解死锁周围发生了什么。然后,在“我的跟踪”处于打开状态的测试环境中复制此功能
- 然后,我在日志文件上运行了一个脚本,看看死锁是否可能以及如何发生。我使用了一个awk脚本,使用以下算法:
- 前每条线
- 如果获得
- 将lockid添加到此线程的当前锁列表
- 将此列表中的每一对锁添加到此线程的一组锁对。例如,对于
锁A->锁B->锁C的列表,生成对
(锁A,锁B),(锁A,锁C),(锁B,锁C)
- 如果释放
- 从该线程的列表尾部删除当前lockid
- 如果获得
- 对于每个锁对,在所有其他线程中搜索反向锁对,每个匹配都是潜在的死锁,因此打印受影响的锁对和线程
- 我没有让算法变得更智能,而是检查了锁获取,看它是否是真正的死锁
- 前每条线
- 您是否仅使用
来保护您的关键部分?您正在使用java.lang.concurrent中的类吗?(这些可能需要特殊处理/仪器)synchronized
- 使用aspects/ASM打印代码位置有多容易?我在C++中使用了<代码> >文件> <代码> >代码>ASM将为您提供类名、方法名和签名
- 无法检测用于保护跟踪/日志记录的锁
- 如果对文件对象使用每个线程的日志文件和线程本地存储,则可以简化检测
- 如何唯一标识同步对象?也许toString()和System.identityHashCode()就足够了,但可能需要更多。我使用C++中的对象地址。
- 并不能让你一路走到那里,但一个好的开始是使用,并抓住一些东西。你可以使用,这相对容易学习,并允许您设置自己的自定义和简化方式来监控线程及其访问的任何锁。我没有使用AspectJ,因此无法保证它的易用性。我曾经创建过一个自定义代码分析器,这大约需要2天的工作。仪器同步的工作应该是类似的。AspectJ应该在您熟悉Aspect之后变得更快、更容易
我已经实现了基于C++的服务器死锁检测跟踪。我是这样做的:
如果你考虑java中的这种方法,需要考虑的是: