Подтвердить что ты не робот

Почему этот код создает тупик?

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");
    }
}

Я никогда не получаю finish печатать и значение i. Почему это так?

4b9b3361

Ответ 1

Вы начинаете с потока 1 ( "основной" поток) и начинаете выполнение статического инициализатора для класса A.

Внутри этого статического инициализатора вы затем запускаете новый поток (2), который использует что-то в классе A. Это означает, что поток 2 должен ждать, пока класс A завершит инициализацию до того, как он продолжит, согласно разделу 12.4.2 JLS:

Если объект класса для C указывает, что инициализация выполняется для C каким-либо другим потоком, затем отпустите LC и заблокируйте текущий поток, пока не сообщите, что завершенная инициализация завершена, и в этот момент повторите этот шаг.

Однако ваш статический инициализатор для A ждет, пока поток 2 не завершит (вызывая join()) до его завершения, что приведет к тупиковой ситуации: статический инициализатор не может завершиться до тех пор, пока поток 2 не завершится, а поток 2 может 't до завершения статического инициализатора...

Результат: не делайте этого:)

Ответ 2

Загрузка классов и статических блоков неявно синхронизируется. Это означает, что вы не можете получить доступ к чему-либо в классе в другом потоке, пока он инициализируется. В этом случае инициализация ожидает поток, который использует A.i. Другими словами, он ждет, пока первый поток завершит статический блок.

Примечание: он не использует нормальную блокировку, и поток утверждает, что находится в состоянии Runnable, даже если он заблокирован.

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)