下面我們來看看下面這段代碼,我們看看它會打印什麼東西出來。
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的設計者們在這個方面做得很不錯。如果你寫了一些複雜的類初始化代碼,很多種情況下,你這是在搬起石頭砸自己的腳。