【问题标题】:How to detect synchronization violations with Java如何使用 Java 检测同步违规
【发布时间】:2008-11-18 14:26:37
【问题描述】:

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

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

我渴望可以为 AWT 调度线程制作类似的东西,如下所示:

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

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

【问题讨论】:

    标签: java multithreading synchronization error-detection


    【解决方案1】:

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

    “Java 并发实践”中有一节是关于测试线程问题的。它特别强调了它的难度。

    【讨论】:

      【解决方案2】:

      当 Java 中的线程出现问题时,它通常与死锁检测有关,而不仅仅是监视哪些线程同时访问同步部分。 JMX 扩展,从 1.5 开始添加到 JRE,可以帮助您检测那些死锁。事实上,我们在我们自己的软件中使用 JMX 来自动检测死锁并跟踪发现死锁的位置。

      这里有一个example关于如何使用它。

      【讨论】:

        【解决方案3】:

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

        同样,FindBugs 有许多相似的checks

        【讨论】:

        • 有用的并发检查...例如? :)
        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

          试试ConTestCovertity

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

          另外,检查这个问题:Unit testing a multithreaded application?

          【讨论】:

            【解决方案6】:

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

            【讨论】:

              【解决方案7】:

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

              也就是说,从您描述的用例来看,这听起来像记住一个线程并对其进行断言这样简单的事情可能足以满足您的需求。

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

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

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

              【讨论】:

                【解决方案8】:

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

                不久前,我使用 JProbe java 分析工具。他们的工具之一(threadalyzer?)寻找线程同步违规。查看他们的网页,我没有看到同名的工具或我记得的工具。但你可能想看看。 http://www.quest.com/jprobe/performance-home.aspx

                【讨论】:

                  【解决方案9】:

                  您可以使用Netbeans profilerJConsole深入检查线程状态

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2018-04-23
                    • 1970-01-01
                    • 2019-07-09
                    • 1970-01-01
                    • 2020-11-04
                    • 2022-09-23
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多