一个线程能否在另一个线程完成静态初始化(class加载)之前进入静态方法?
Can a thread enter a static method before static initialization (class loading) is complete by another thread?
假设我们有以下 classes 和两个线程 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() 获取锁定 class 加载 A.
2) t2 执行 B.bSomeMeth() 获取 B 的 class 加载锁。
3) t1 继续执行 B.bMeth() 并在持有 A 的锁的同时要求 B 的锁。
4) t2 继续执行 A.aMeth() 并在为 B 保持锁定的同时要求为 A 锁定。
这会导致死锁。但在我的例子中,t2 实际上进入 aMeth
() 并在访问静态成员 str
时被阻塞。所以我想知道在特殊情况下线程是否可以在初始化之前进入静态方法
在我的测试运行中,t2 总是像预期的那样在 A.aMeth() 处被阻塞,所以是否存在任何极端情况,它可以进入它并在 str
处被阻塞,JIT 优化,如方法内联等
不,class 只能由一个线程初始化一次。如果另一个线程访问同一个 class,这个线程将在初始化完成时阻塞。
假设我们有以下 classes 和两个线程 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() 获取锁定 class 加载 A.
2) t2 执行 B.bSomeMeth() 获取 B 的 class 加载锁。
3) t1 继续执行 B.bMeth() 并在持有 A 的锁的同时要求 B 的锁。
4) t2 继续执行 A.aMeth() 并在为 B 保持锁定的同时要求为 A 锁定。
这会导致死锁。但在我的例子中,t2 实际上进入 aMeth
() 并在访问静态成员 str
时被阻塞。所以我想知道在特殊情况下线程是否可以在初始化之前进入静态方法
在我的测试运行中,t2 总是像预期的那样在 A.aMeth() 处被阻塞,所以是否存在任何极端情况,它可以进入它并在 str
处被阻塞,JIT 优化,如方法内联等
不,class 只能由一个线程初始化一次。如果另一个线程访问同一个 class,这个线程将在初始化完成时阻塞。