(在 Java 中使用静态初始化器是否是一个好主意超出了这个问题的范围。)
我在 Scala 应用程序中遇到了死锁,我认为这是由编译类中的互锁静态初始化器引起的。
我的问题是如何检测和诊断这些死锁——我发现当涉及静态初始化程序块时,用于死锁的普通 JVM 工具似乎不起作用。
下面是一个简单的 Java 应用程序示例,它在静态初始化程序中死锁:
public class StaticDeadlockExample implements Runnable
{
static
{
Thread thread = new Thread(
new StaticDeadlockExample(),
"StaticDeadlockExample child thread");
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args)
{
System.out.println("in main");
}
public static void sayHello()
{
System.out.println("hello from thread " + Thread.currentThread().getName());
}
@Override
public void run() {
StaticDeadlockExample.sayHello();
}
}
如果您启动此应用程序,它就会陷入僵局。死锁时的堆栈跟踪(来自jstack
)包含以下两个死锁线程:
"StaticDeadlockExample child thread" prio=6 tid=0x000000006c86a000 nid=0x4f54 in Object.wait() [0x000000006d38f000]
java.lang.Thread.State: RUNNABLE
at StaticDeadlockExample.run(StaticDeadlockExample.java:37)
at java.lang.Thread.run(Thread.java:619)
Locked ownable synchronizers:
- None
"main" prio=6 tid=0x00000000005db000 nid=0x2fbc in Object.wait() [0x000000000254e000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x000000004a6a7870> (a java.lang.Thread)
at java.lang.Thread.join(Thread.java:1143)
- locked <0x000000004a6a7870> (a java.lang.Thread)
at java.lang.Thread.join(Thread.java:1196)
at StaticDeadlockExample.<clinit>(StaticDeadlockExample.java:17)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:116)
Locked ownable synchronizers:
- None
我的问题如下
- 为什么第一个线程实际上正在等待锁,但它被标记为 RUNNABLE?我可以以某种方式检测到该线程的“真实”状态吗?
- 为什么两个线程都没有被标记为拥有任何(相关)锁,而实际上一个线程持有静态初始化器锁,另一个线程正在等待它?我可以以某种方式检测静态初始化程序锁所有权吗?
Scala 很容易陷入陷阱。
简单的解决方法或诊断(如果您在堆栈跟踪中看到 clinit)是让您的对象扩展 App,以让 DelayedInit 将您的代码从静态初始化程序中取出。
一些澄清链接:
https://issues.scala-lang.org/browse/SI-7646
Scala:对象初始值设定项中的并行集合导致程序挂起
http://permalink.gmane.org/gmane.comp.lang.scala.user/72499
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)