问题
class A {
static final int i;
static {
i = 128;
Thread t = new Thread() {
public void run() {
System.out.println("i=" + i);
}
};
t.start();
try {
t.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public class MainTesting {
public static void main(String[] args) {
A a = new A();
System.out.println("finish");
}
}
I never get finish
get printed and value of i.
Why is it so?
回答1:
You start off on thread 1 (the "main" thread), and start executing the static initializer for the A
class.
Within that static initializer, you then start a new thread (2), which uses something within the A
class. That means that thread 2 needs to wait until the A
class has finished initilaizing before it will proceed, as per section 12.4.2 of the JLS:
If the Class object for C indicates that initialization is in progress for C by some other thread, then release LC and block the current thread until informed that the in-progress initialization has completed, at which time repeat this step.
However, your static initializer for A
waits until thread 2 has completed (by calling join()
) before it completes, leading to deadlock: the static initializer can't complete until thread 2 has completed, and thread 2 can't complete until the static initializer has completed...
Upshot: don't do this :)
回答2:
Loading of classes and static blocks are implicitly synchronized This means you cannot access anything in a class in another thread while it is being initialised. In this case the initialisation is waiting for a thread which is using A.i
. In other words, it is waiting for the first thread to finish the static block.
Note: it doesn't use a normal lock and the thread claims to be in a Runnable state even though it is deadlocked.
2013-06-21 11:20:40
Full thread dump Java HotSpot(TM) 64-Bit Server VM (23.21-b01 mixed mode):
"Thread-0" prio=6 tid=0x000000000d55d000 nid=0x3cc4 in Object.wait() [0x000000000dbdf000]
java.lang.Thread.State: RUNNABLE
at Main$1.run(Main.java:14) <- where A.i is referenced.
"main" prio=6 tid=0x00000000022df000 nid=0x3284 in Object.wait() [0x000000000257e000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000007d5610448> (a Main$1)
at java.lang.Thread.join(Thread.java:1258)
- locked <0x00000007d5610448> (a Main$1)
at java.lang.Thread.join(Thread.java:1332)
at Main.<clinit>(Main.java:19)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:188)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:113)
来源:https://stackoverflow.com/questions/17236561/why-does-this-code-produce-deadlock