如何使用Java检测同步违规

时间:2008-11-18 14:26:37

标签: java multithreading synchronization error-detection

我想知道有什么好方法可以对同步进行断言或者某些东西,以便我可以检测同步违规(在测试时)。

那将用于例如我有一个非线程安全的类并且不会是线程安全的情况。通过某种方式,如果从多个线程调用某些方法,我会有一些断言可以通知我(日志或其他东西)。

我渴望通过以下方式为AWT调度线程做类似的事情:

public static void checkDispatchThread() {
    if(!SwingUtilities.isEventDispatchThread()) {
        throw new RuntimeException("GUI change made outside AWT dispatch thread");
    }
}

我只想要更通用的东西。问题描述不是很清楚,但我希望有人有一些好的方法=)

9 个答案:

答案 0 :(得分:2)

我想你正在寻找圣杯。 AFAIK它不存在,Java不是一种允许轻松创建这种方法的语言。

“Java Concurrency in Practice”有一节关于测试线程问题。它特别关注它的难度。

答案 1 :(得分:2)

当Java中的线程出现问题时,它通常与死锁检测有关,而不仅仅是监视线程同时访问同步部分的内容。从{1.5开始添加到JRE的JMX扩展可以帮助您检测这些死锁。实际上,我们在自己的软件中使用JMX来自动检测死锁,找到它的痕迹。

以下是关于如何使用它的example

答案 2 :(得分:2)

IntelliJ IDEA有很多有用的并发inspections。例如,当您在同步和非同步上下文中访问同一个对象时,当您在非最终对象上进行同步时,它会发出警告。

同样,FindBugs有许多相似的checks

答案 3 :(得分:1)

除了@ Fernando提到线程死锁之外,多线程的另一个问题是并发修改及其可能导致的问题。

Java在内部做的一件事是集合类保留了更新次数的计数。然后迭代器检查每个.next()上的值与创建交互器时的值,以查看在迭代时集合是否已更新。我认为这个原则可以更普遍地使用。

答案 4 :(得分:1)

尝试ConTestCovertity

这两个工具分析代码以确定哪些部分数据可能在线程之间共享,然后他们检测代码(将额外的字节码添加到已编译的类)以检查当两个线程尝试更改某些数据时它是否会中断同一时间。然后两个线程一遍又一遍地运行,每次以稍微不同的时间偏移启动它们以获得许多可能的访问模式组合。

另外,请检查此问题:Unit testing a multithreaded application?

答案 5 :(得分:1)

您可能对Peter Veentjer撰写的一种方法感兴趣,他称之为The Concurrency Detector。我不相信他已经开源了这个,但正如他所描述的那样,基本的想法是使用AOP来检测你感兴趣的分析代码,并记录哪个线程触及了哪个字段。之后,需要手动或自动解析生成的日志。

答案 6 :(得分:1)

如果您可以识别线程不安全的类,静态分析可能会告诉您它们是否“逃脱”以使多个线程可见。通常情况下,程序员会这样做,但显然他们在这方面容易出错。工具应该能够使用类似的方法。

那就是说,从你描述的用例来看,它听起来就像记住一个线程一样简单,在它上面做断言就足以满足你的需求。

class Foo {

  private final Thread owner = Thread.currentThread();

  void x() {
    assert Thread.currentThread() == owner;
    /* Implement method. */
  }

}

即使禁用断言,仍然会填充所有者引用,因此它并非完全“免费”。我也不想用这个样板来混乱我的许多课程。

Thread.holdsLock(Object)方法也可能对您有用。

答案 7 :(得分:0)

对于您提供的具体示例,SwingLabs有一些帮助程序代码来检测事件线程违规并挂起。 https://swinghelper.dev.java.net/

前段时间,我使用了JProbe java分析工具。他们的一个工具(threadalyzer?)寻找线程同步违规。看着他们的网页,我看不到那个名字的工具或者我记得的东西。但你可能想看一看。 http://www.quest.com/jprobe/performance-home.aspx

答案 8 :(得分:-1)

您可以使用Netbeans profilerJConsole来检查线程状态的深度