我在维护的Swing应用程序中遇到了僵局,尽管我有一个可行的解决方法,但我不确定我是否了解自己在做什么,还没有隐藏可能弹出的竞争条件稍后再试。
线程跟踪显示死锁发生在两个线程AWT-EventQueue-0和AWT- EventQueue-1之间。我的第一个问题是,如果其中一个是臭名昭著的事件调度线程。这两个线程在堆栈跟踪的底部都有以下内容:
at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)
我认为问题的根源在于应用程序类将域数据与图形组件混合在一起,在这种情况下,两个线程都试图锁定a java.awt.Component$AWTTreeLock和我自己的对象之一(比如X)。我的解决方法是SwingUtilities.invokeLater()在X锁定的地方使用,即使X已经在EDT上了。根据Javadoc,这意味着调用“推迟到所有未决事件都已处理完为止”。但是,我不太确定这是否是解决方案,无论如何我都不清楚为什么似乎有两个EDT。
java.awt.Component$AWTTreeLock
SwingUtilities.invokeLater()
谁能解释发生了什么?我可以尝试提供该代码的简化版本,但可能要花一些时间才能编辑出无关紧要的并发症。
感谢Yishai为我指出正确的方向。该应用程序实例化其自己的子类,java.awt.EventQueue并Toolkit.getDefaultToolkit().getSystemEventQueue().push(newQueue)用于替换原始队列。AWT- EventQueue-0在事件开始到达线程上的新队列的同时,原始队列仍必须在其线程上处理任务AWT-EventQueue-1,从而导致死锁。
java.awt.EventQueue
Toolkit.getDefaultToolkit().getSystemEventQueue().push(newQueue)
AWT- EventQueue-0
AWT-EventQueue-1