成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【Java】類的循環(huán)初始化是否會引起死鎖?

crelaber / 2754人閱讀

摘要:前置知識類的生命周期場景設(shè)計(jì)和推測情況在類中的初始化中實(shí)例化在類的初始化中實(shí)例化類設(shè)計(jì)類靜態(tài)變量靜態(tài)變量之后在靜態(tài)初始化塊里賦值為實(shí)例變量之后再初始化塊中賦值為構(gòu)造函數(shù)類靜態(tài)變量靜態(tài)變量之后在靜態(tài)初始化塊里賦值為實(shí)例變量之后再初始化塊中賦值

前置知識: 類的生命周期

場景設(shè)計(jì)和推測

情況:

在類A中的初始化中實(shí)例化B

在類B的初始化中實(shí)例化A

類設(shè)計(jì)

A類:

靜態(tài)變量a=new B();靜態(tài)變量a1=1(之后在靜態(tài)初始化塊里賦值為2);

實(shí)例變量a2=11(之后再初始化塊中賦值為12);

構(gòu)造函數(shù);

B類:

靜態(tài)變量b=new A();靜態(tài)變量b1=3(之后在靜態(tài)初始化塊里賦值為4);

實(shí)例變量b2=21(之后再初始化塊中賦值為22);

構(gòu)造函數(shù);

猜想執(zhí)行結(jié)果: 由于類初始化之后類實(shí)例化,所以A類初始化需要B實(shí)例化,B實(shí)例化又需要A初始化,造成循環(huán)依賴,最終結(jié)果為死鎖

打點(diǎn)位置:

類加載結(jié)束點(diǎn)(text: Loaded Main2 from file)

類初始化開始點(diǎn)/結(jié)束點(diǎn)(text: Class A2 init)

實(shí)例初始化開始點(diǎn)/結(jié)束點(diǎn)(text: Instance A2 init)

構(gòu)造函數(shù)結(jié)束點(diǎn)(text: Instance A2 new)

場景代碼
class A2 {
    static {
        System.out.println("Class A2 init start");
    }

    static B2 a = new B2();
    static int a1 = 1;

    {
        System.out.println("Instance A2 init start. 	a=" + a + " 	a1=" + a1 + " 	a.b2=" + (a == null ? "NPE" : a.b2) + " 	b=" + B2.b + " 	b1=" + B2.b1 + " 	b.a2=" + (B2.b == null ? "NPE" : B2.b.a2));
    }

    public int a2 = 11;

    static {
        a1 = 2;
        System.out.println("Class A2 init end. 	a=" + a + " 	a1=" + a1 + " 	a.b2=" + (a == null ? "NPE" : a.b2) + " 	b=" + B2.b + " 	b1=" + B2.b1 + " 	b.a2=" + (B2.b == null ? "NPE" : B2.b.a2));
    }

    {
        a2 = 12;
        System.out.println("Instance A2 init end. 	a=" + a + " 	a1=" + a1 + " 	a.b2=" + (a == null ? "NPE" : a.b2) + " 	b=" + B2.b + " 	b1=" + B2.b1 + " 	b.a2=" + (B2.b == null ? "NPE" : B2.b.a2));
    }

    public A2() {
        System.out.println("Instance A2 new. 	a=" + a + " 	a1=" + a1 + " 	a.b2=" + (a == null ? "NPE" : a.b2) + " 	b=" + B2.b + " 	b1=" + B2.b1 + " 	b.a2=" + (B2.b == null ? "NPE" : B2.b.a2));
    }
}

class B2 {
    static {
        System.out.println("Class B2 init start");
    }

    static A2 b = new A2();
    static int b1 = 3;

    {
        System.out.println("Instance B2 init start. 	b=" + b + " 	b1=" + b1 + " 	b.a2=" + (b == null ? "NPE" : b.a2) + " 	a=" + A2.a + " 	a1=" + A2.a1 + " 	a.b2=" + (A2.a == null ? "NPE" : A2.a.b2));
    }

    public int b2 = 21;

    static {
        b1 = 4;
        System.out.println("Class B2 init end. 	b=" + b + " 	b1=" + b1 + " 	b.a2=" + (b == null ? "NPE" : b.a2) + " 	a=" + A2.a + " 	a1=" + A2.a1 + " 	a.b2=" + (A2.a == null ? "NPE" : A2.a.b2));
    }

    {
        b2 = 22;
        System.out.println("Instance B2 init end. 	b=" + b + " 	b1=" + b1 + " 	b.a2=" + (b == null ? "NPE" : b.a2) + " 	a=" + A2.a + " 	a1=" + A2.a1 + " 	a.b2=" + (A2.a == null ? "NPE" : A2.a.b2));
    }

    public B2() {
        System.out.println("Instance B2 new. 	b=" + b + " 	b1=" + b1 + " 	b.a2=" + (b == null ? "NPE" : b.a2) + " 	a=" + A2.a + " 	a1=" + A2.a1 + " 	a.b2=" + (A2.a == null ? "NPE" : A2.a.b2));
    }
}

class Main2 {
    static public void main(String... args) {
        System.out.println("A2 a=" + A2.a);
        System.out.println("A2 a1=" + A2.a1);
        System.out.println("A2 a2=" + B2.b.a2);
        System.out.println("B2 b=" + B2.b);
        System.out.println("B2 b1=" + B2.b1);
        System.out.println("B2 b2=" + A2.a.b2);
    }
}
執(zhí)行結(jié)果分析

程序輸出結(jié)果:

1. [Loaded Main2 from file:/Users/jiadongy/JVM_Learning_Sample/out/production/JVM_Learning_Sample/]
2. [Loaded A2 from file:/Users/jiadongy/JVM_Learning_Sample/out/production/JVM_Learning_Sample/]
3. Class A2 init start
4. [Loaded B2 from file:/Users/jiadongy/JVM_Learning_Sample/out/production/JVM_Learning_Sample/]
5. Class B2 init start
6. Instance A2 init start. a=null a1=0 a.b2=NPE b=null b1=0 b.a2=NPE
7. Instance A2 init end.      a=null a1=0 a.b2=NPE b=null b1=0 b.a2=NPE
8. Instance A2 new.         a=null a1=0 a.b2=NPE b=null b1=0 b.a2=NPE
9. Class B2 init end.              b=A2@61bbe9ba b1=4 b.a2=12 a=null a1=0 a.b2=NPE
10. Instance B2 init start.       b=A2@61bbe9ba b1=4 b.a2=12 a=null a1=0 a.b2=NPE
11. Instance B2 init end.          b=A2@61bbe9ba b1=4 b.a2=12 a=null a1=0 a.b2=NPE
12. Instance B2 new.             b=A2@61bbe9ba b1=4 b.a2=12 a=null a1=0 a.b2=NPE
13. Class A2 init end.      a=B2@610455d6 a1=2 a.b2=22 b=A2@61bbe9ba b1=4 b.a2=12
14. A2 a=B2@610455d6
15. A2 a1=2
16. A2 a2=12
17. B2 b=A2@61bbe9ba
18. B2 b1=4
19. B2 b2=22

把它轉(zhuǎn)化為下面的表格,更加清晰地描述A/B各個階段執(zhí)行的過程:

A B
A類加載完成
A類初始化 - 開始
B類加載完成
B類初始化 - 開始
A類實(shí)例初始化 - 開始
A類實(shí)例初始化 - 結(jié)束
A類實(shí)例構(gòu)造函數(shù)執(zhí)行完成
B類初始化 - 結(jié)束
B類實(shí)例初始化 - 開始
B類實(shí)例初始化 - 結(jié)束
B類實(shí)例構(gòu)造函數(shù)執(zhí)行完成
A類初始化 - 結(jié)束

可以看到在A類初始化的過程中,A類被實(shí)例化了(并且該階段正常結(jié)束了),也就是說類的初始化階段并不是原子的/排他的.
如在本例中,A類實(shí)例化階段的結(jié)束早于其類初始化階段,A類實(shí)例化完成時,A類的靜態(tài)變量還未被初始化.

Reference.1中已經(jīng)描述了這種情況:

_加載/驗(yàn)證/準(zhǔn)備/初始化和卸載這5個階段的順序是確定的_,類的加載過程必須按照這種順序按部就班的開始...注意,這里筆者寫的是按部就班的"開始",而不是按部就班的"進(jìn)行"或"完成",強(qiáng)調(diào)這點(diǎn)是因?yàn)檫@些階段通都是相互交叉混合式進(jìn)行的,通常會在一個階段執(zhí)行的過程中調(diào)用/激活另外一個階段

                                                          <<深入理解Java虛擬機(jī)>>P210
總結(jié)

類的循環(huán)初始化不會引起死鎖

5個階段的開始是有順序的,結(jié)束則不一定

階段不是排他的/臨界的

循環(huán)初始化可能引起意料之外的情況,盡量避免

eg.類在初始化過程中修改另一個類的變量,導(dǎo)致另一個類得到了意料之外的初始值

Reference

深入理解Java虛擬機(jī)

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/67280.html

相關(guān)文章

  • 【面試】Java相關(guān)

    摘要:可能會持有相同的值對象但鍵對象必須是唯一的。當(dāng)有新任務(wù)到達(dá)時,線程池沒有線程則創(chuàng)建線程處理,處理完成后該線程緩存秒,過期后回收,線程過期前有新任務(wù)到達(dá)時,則使用緩存的線程來處理。解決死鎖問題的三種方法預(yù)防死鎖檢測死鎖及避免死鎖。 最近辭職準(zhǔn)備面試,順便整理一下面試題分享給大家,如有錯誤歡迎指出 01. 你對面向?qū)ο笏枷氲睦斫猓?面向?qū)ο缶幊毯喎QOOP,是開發(fā)程序的一種方法、思想。面向...

    icattlecoder 評論0 收藏0
  • Java面試題

    摘要:近段時間在準(zhǔn)備實(shí)習(xí)的面試,在網(wǎng)上看到一份面試題,就慢慢試著做,爭取每天積累一點(diǎn)點(diǎn)?,F(xiàn)在每天給自己在面試題編寫的任務(wù)是題,有時候忙起來可能就沒有時間寫了,但是爭取日更,即使當(dāng)天沒更也會在之后的更新補(bǔ)上。 ????近段時間在準(zhǔn)備實(shí)習(xí)的面試,在網(wǎng)上看到一份面試題,就慢慢試著做,爭取每天積累一點(diǎn)點(diǎn)。????暫時手頭上的面試題只有一份,題量還是挺大的,有208題,所以可能講的不是很詳細(xì),只是我自...

    OnlyMyRailgun 評論0 收藏0
  • Java 同步鎖

    摘要:如果同一個線程再次請求該鎖,計(jì)數(shù)器會遞增,每次占有的線程退出同步代碼塊時計(jì)數(shù)器會遞減,直至減為時鎖才會被釋放。表示或在該上的所有線程的個數(shù)用來實(shí)現(xiàn)重入鎖的計(jì)數(shù)。只有兩種可能的值表示沒有需要喚醒的線程表示要喚醒一個繼任線程來競爭鎖。 一、synchronized 1.類型 (1)對象鎖 對象鎖是作用在實(shí)例方法或者一個對象實(shí)例上面的 一個類可以有多個實(shí)例對象,因此一個類的對象鎖可能會有多個...

    xi4oh4o 評論0 收藏0
  • Java 中15種鎖的介紹:公平鎖,可重入鎖,獨(dú)享鎖,互斥鎖,樂觀鎖,分段鎖,自旋鎖等等

    摘要:公平鎖非公平鎖公平鎖公平鎖是指多個線程按照申請鎖的順序來獲取鎖。加鎖后,任何其他試圖再次加鎖的線程會被阻塞,直到當(dāng)前進(jìn)程解鎖。重量級鎖會讓其他申請的線程進(jìn)入阻塞,性能降低。 Java 中15種鎖的介紹 在讀很多并發(fā)文章中,會提及各種各樣鎖如公平鎖,樂觀鎖等等,這篇文章介紹各種鎖的分類。介紹的內(nèi)容如下: 公平鎖 / 非公平鎖 可重入鎖 / 不可重入鎖 獨(dú)享鎖 / 共享鎖 互斥鎖 / 讀...

    LeoHsiun 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<