java - 一个线程可以在另一个线程完成静态初始化(类加载)之前进入静态方法吗?

标签 java multithreading deadlock static-initializer

假设我们有以下类和两个线程 t1,t2。

public class A {
        static String str = "abc";

        static {
          B.bMeth();
        }

        static void aMeth() {
            System.out.println("A::meth()");
            str = "abc2";
        }

        static void aSomeMeth() {}
    }

public class B {

        static {
            A.aMeth();
        }

        static void bMmeth() {}
        static void bSomeMeth() {}
    }

以下是死锁发生的顺序:

1) t1 执行 A.aSomeMeth(),它获取 A 的类加载锁。

2) t2 执行 B.bSomeMeth(),它获取 B 的类加载锁。

3) t1 继续执行 B.bMeth() 并要求对 B 进行锁定,同时保持对 A 的锁定。

4) t2 继续执行 A.aMeth() 并需要对 A 进行锁定,同时对 B 保持锁定。

这会导致死锁。但在我的例子中,t2 实际上进入了 aMeth(),并且在访问静态成员 str 时被阻止。所以我想知道在特殊情况下线程是否可以在初始化之前进入静态方法。

在我的测试运行中,t2 总是按预期在 A.aMeth() 处被阻止,因此是否存在任何极端情况,它可以进入它并在 str 上被阻止,JIT 优化(例如方法)内联等

最佳答案

不可以,一个类只能由一个线程初始化一次。如果另一个线程访问同一个类,则该线程将在初始化完成时阻塞。

关于java - 一个线程可以在另一个线程完成静态初始化(类加载)之前进入静态方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47752358/

相关文章:

java - 不使用 setXXXSize 的 JComboBox 的 Swing BoxLayout 问题

java - 验证文本输入时如何避免 try-catch

concurrency - 为什么这段 Go 代码会死锁?

c# - 线程池死锁与 Task.Result

mysql - 我最近升级到 mysql 5.7 并观察到频繁的死锁问题。是否有任何与锁定 5.7 相关的更改?

java - 安卓 11.0 : How to delete a file with Storage Access Framework?

java - 解决数组越界问题

java - 如何阻止另一个 Java 线程?

java - 等待/通知死锁

multithreading - intellij-不在多线程代码中的所有断点上停止