【问题标题】:why does this code produce deadlock? [duplicate]为什么这段代码会产生死锁? [复制]
【发布时间】:2013-06-21 23:22:47
【问题描述】:
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 的值。 为什么会这样?

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    您从线程 1(“主”线程)开始,并开始执行 A 类的静态初始化程序。

    在该静态初始化程序中,然后您启动一个新线程 (2),该线程使用 A 类中的某些内容。这意味着线程 2 需要等到 A 类完成初始化才能继续,根据section 12.4.2 of the JLS

    如果 C 的 Class 对象指示其他线程正在对 C 进行初始化,则释放 LC 并阻塞当前线程,直到通知正在进行的初始化已完成,此时重复此步骤。

    但是,A 的静态初始化程序会等到线程 2 完成(通过调用 join()it 完成,从而导致死锁:静态初始化程序直到线程 2 才能完成已经完成,而线程 2 直到静态初始化程序完成后才能完成......

    结果:不要这样做:)

    【讨论】:

    • 请不要介意,但我想你已经在stackoverflow.com/questions/6686333/…回答了这个问题
    • @MickJ:是的,我很难记住过去两个月我回答的所有问题,更不用说过去两年了 :)
    • 我能理解。成为 Jon Skeet 的负担 :) 我还是喜欢它。像我这样的新人在得到答案而不是愤怒的否决票和“在发布之前做一些研究”时会感到更受欢迎。我喜欢这样 +1
    【解决方案2】:

    类和静态块的加载是隐式同步的 这意味着在初始化时,您不能在另一个线程中访问类中的任何内容。在这种情况下,初始化正在等待使用A.i 的线程。换句话说,它正在等待第一个线程完成静态块。

    注意:它不使用普通锁,并且线程声称处于可运行状态,即使它已死锁。

    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)
    

    【讨论】:

    • “静态块是隐式同步的”同步发生在对象上,对吧?但静态块可能没有任何与之关联的对象..
    • 静态块与ClassName.class 对象相关联。如果您执行static synchronized 方法,这就是您要锁定的对象。我不知道类加载是这样实现的,还是类加载器上有锁或一些全局锁。我怀疑它依赖于 JVM。
    猜你喜欢
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    • 2012-08-27
    • 1970-01-01
    • 2017-07-09
    • 1970-01-01
    • 2020-08-20
    • 1970-01-01
    相关资源
    最近更新 更多