下面我们来看看下面这段代码,我们看看它会打印什么东西出来。
package test85;
/**
*
* @author 王新
*这个程序会发生死锁。。。。。。。。。。
*详细见 java解惑 85题
*/
public class Lazy {
private static boolean initialized = false;
static {
Thread t = new Thread(new Runnable() {
public void run() {
initialized = true;
}
});
t.start();
try{
t.join();
}catch (InterruptedException e){
throw new AssertionError(e);
}
}
public static void main(String[] args){
System.out.println(initialized);
}
}
我们看上面的代码开始定义一个静态的boolean initialized 其初始值为false。然后再定义一个线程,在他的run方法中我们将 initialized 设置为true,主线程启动了后台线程,然后有调用join()方法等待后台线程结束,当后台线程执行完后我们可以知道 initialized 被置为true,然后我们在主方法中输出 initialized
的值。但是我们的程序不会输出任何的东西,他应该是被挂起了。。。。
在解决这个问题我们需要知道一个初始化的细节。当一个线程访问一个类的某个成员的时候,它会去检查这个类是否已经被初始化。在一般情况下,我们有四种情况发生。
- 这个类尚未被初始化。
- 这个类正在被当前线程初始化:这是对初始化的递归请求。
- 这个类正在被其他线程而不是当前线程初始化。
- 这个类已经被初始化。
总之,在类的初始化期间等待某个后台线程很可能会造成死锁。要让类初始化的动作序列尽可能地简单。类的自动初始化被公认为是语言设计上的难题,Java的设计者们在这个方面做得很不错。如果你写了一些复杂的类初始化代码,很多种情况下,你这是在搬起石头砸自己的脚。