<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    我思故我強

    Java線程之同步化(Synchronized)

    1.? 如果一個對象所持有的數據可以被多線程同時共享存取,必須考慮到數據同步的問題。所謂數據同步指的是兩份數據的整體性和一致性。數據在多線程下共享時容易由于同時多個線程可能更新同一個對象的信息,而造成對象數據的不同步,因為數據的不同步可能引發的錯誤通常不易察覺,而且可能是在程序執行了幾千幾萬次之后,才會發生錯誤。這通常會發生在產品已經上線之后,甚至是程序已經執行了幾年之后。

    2. 舉個簡單的例子,設計了一個PersonalInfo類:???

    Java代碼?
    1. package ?ysu.hxy; ??
    2. ??
    3. public ? class ?PersonalInfo? ??
    4. { ??
    5. ???? private ?String?name; ??
    6. ???? private ?String?id; ??
    7. ???? private ? int ?count; ??
    8. ??
    9. ???? public ?PersonalInfo() ??
    10. ????{ ??
    11. ????????name?=? "nobody" ; ??
    12. ????????id?=? "N/A" ; ??
    13. ????} ??
    14. ??
    15. ???? public ? void ?setNameAndID(String?name,String?id) ??
    16. ????{ ??
    17. ???????? this .name?=?name; ??
    18. ???????? this .id?=?id; ??
    19. ???????? if (!checkNameAndIDEqual()) ??
    20. ????????{ ??
    21. ?????????????System.out.println(count?+? ")?illegal?name?or?ID..." ); ??
    22. ????????} ??
    23. ????????count?++; ??
    24. ????} ??
    25. ??
    26. ???? private ? boolean ?checkNameAndIDEqual(){ ??
    27. ???????? return ?(name.charAt( 0 )?==?id.charAt( 0 ))??? true : false ; ??
    28. ????} ??
    29. }??

    ?單就這個類本身而言,它并沒有任何的錯誤,但如果它被用于多線程的程序中,而且同一個對象被多個線程存取時,就會有可能發生錯誤。下面是一個簡單的測試程序,看看PersonalInfo類在多線程共享數據下會發生什么問題。

    Java代碼?
    1. package ?ysu.hxy; ??
    2. ??
    3. public ? class ?PersonalInfoTest? ??
    4. { ??
    5. ???? public ? static ? void ?main(String[]?args)? ??
    6. ????{ ??
    7. ???????? final ?PersonalInfo?person?=? new ?PersonalInfo(); ??
    8. ??
    9. ???????? //假設會能兩個線程可能更新person對象? ??
    10. ????????Thread?thread1?=? new ?Thread( new ?Runnable()?{ ??
    11. ???????????? public ? void ?run()?{ ??
    12. ???????????????? while ( true ){ ??
    13. ????????????????????person.setNameAndID( "Justin?Lin" , "J.L" ); ??
    14. ????????????????} ??
    15. ????????????} ??
    16. ????????}); ??
    17. ??
    18. ????????Thread?thread2?=? new ?Thread( new ?Runnable()?{ ??
    19. ???????????? public ? void ?run()?{ ??
    20. ???????????????? while ( true ){ ??
    21. ????????????????????person.setNameAndID( "Shang?Hwang?Lin" , "S.H" ); ??
    22. ????????????????} ??
    23. ????????????} ??
    24. ????????}); ??
    25. ??
    26. ????????System.out.println(); ??
    27. ??
    28. ????????thread1.start(); ??
    29. ????????thread2.start(); ??
    30. ????} ??
    31. }??

    ?

    執行結果:

    D:\hxy>java ysu.hxy.PersonalInfoTest
    開始測試...
    23466451) illegal name or ID...
    78044494) illegal name or ID...
    101630476) illegal name or ID...
    106496643) illegal name or ID...
    145330181) illegal name or ID...
    169674022) illegal name or ID...
    174072203) illegal name or ID...
    214717201) illegal name or ID...
    219668799) illegal name or ID...
    240921750) illegal name or ID...
    265875722) illegal name or ID...
    270920923) illegal name or ID...
    281256783) illegal name or ID...

    這個程序出現了錯誤,在23466451次的setNameAndID()執行時就開始了。如果程序完成并開始應用于實際場合之后,這個時間點可能是幾個月甚至是幾年之后。問題出在這里:

    Java代碼?
    1. public ? void ?setNameAndID(String?name,String?id) ??
    2. ????{ ??
    3. ???????? this .name?=?name; ??
    4. ???????? this .id?=?id; ??
    5. ???????? if (!checkNameAndIDEqual()) ??
    6. ????????{ ??
    7. ?????????????System.out.println(count?+? ")?illegal?name?or?ID..." ); ??
    8. ????????} ??
    9. ????????count?++; ??
    10. ????}??

    ????? 雖然傳遞給setNameAndID()的變量并沒有問題,在某個時間點時,thread1設定了Justin Lin、J.L給name和id,在進行if測試的前一刻,thread2可能此時剛好調用setNameAndID("Shang Hwang","S.H")。在name被設定為Shang HWang時,checkNameAndIDEqual()開始執行,此時name等于Shang HWang,而id還是J.L。所以,checkNameAndIDEqual()就會返回false,結果就顯示了錯誤信息。

    ?????? 必須同步數據對對象的更新,方法在有一個線程正在設定person對象的數據時,不可以被另一個線程同時進行設定。可以使用synchronized關鍵詞來進行這個動作。

    Java代碼?
    1. public ? synchronized ? void ?setNameAndID(String?name,String?id) ??
    2. ????{ ??
    3. ???????? this .name?=?name; ??
    4. ???????? this .id?=?id; ??
    5. ???????? if (!checkNameAndIDEqual()) ??
    6. ????????{ ??
    7. ?????????????System.out.println(count?+? ")?illegal?name?or?ID..." ); ??
    8. ????????} ??
    9. ????????count?++; ??
    10. ????}??

    ?這是synchronized關鍵詞的一個使用方式,用于方法上讓方法的范圍內都成為被同步化區域。被同步化區域在有一個線程占據時就像一個禁區,不允許其他線程進入。由于同時間只能有一個線程在被同步化區域,所以更新共享數據時,就像單線程程序在更新數據一樣,以保證對象中的數據會與給定的數據同步。

    ? sychronized的設定不只可用于方法上,也可以用于限定某個程序區塊上被同步化區域。例如:?

    Java代碼?
    1. public ? void ?setNameAndID(String?name,String?id) ??
    2. ??{? //同步某個程序區塊 ??
    3. ??????? synchronized ( this ) ??
    4. ???{ ??
    5. ??????? this .name?=?name; ??
    6. ??????? this .id?=?id; ??
    7. ??????? if (!checkNameAndIDEqual()) ??
    8. ??????????{ ??
    9. ???????????????System.out.println(count+ ")?illegal?name?or?ID..." ); ??
    10. ??????????} ??
    11. ???} ??
    12. }??

    ?? 這個程序片段的意思是,在線程執行到synchronized設定的被同步化區塊時鎖定當前對象,這樣就沒有其他線程可以來執行這個被同步化區塊。這個方式可以應用于您不想鎖定整個方法區塊,而只是想在更新共享數據時再確保對象與數據的同步化。由于只鎖定方法中的某個區塊,在執行完區塊后即釋放對對象的鎖定,以便讓其他線程能有機會對對象進行操作,相對于鎖定整個方法區塊效率較高。

    ?? 也可以標示某個對象要求同步化。例如在多線程中存取同一個ArrayList對象時,由于ArrayList并沒有實現數據存取時的同步化,所以當它使用多線程環境時,必須注意多個線程存取同一個ArrayList時,有可能發生兩個以上的線程將數據存入ArrayList的同一個位置,造成數據的相互覆蓋。為了確保數據存入時的正確性,可以在存取ArrayList對象時要求同步化。例如:

    Java代碼?
    1. //arraylist參考至一個ArrayList的一個實例 ??
    2. synchronized (arraylist) ??
    3. { ??
    4. ?????arrayList.add( new ?SomeClass()); ??
    5. }??

    ?同步化確保數據的同步,但所犧牲的就是在于一個線程占據同步化區塊,而其他線程等待它釋放區塊執行權時的延遲。這在線程少時可能看不出來,但在線程多的環境中必然造成一定的效率問題(例如大型網站的多人聯機時)。

    posted on 2009-10-14 11:52 李云澤 閱讀(444) 評論(0)  編輯  收藏 所屬分類: 面試筆試相關的

    主站蜘蛛池模板: 国产乱妇高清无乱码免费| 国内自产少妇自拍区免费| 亚洲真人无码永久在线| 亚洲AV无码AV男人的天堂不卡| 国产免费女女脚奴视频网| 亚洲一级二级三级不卡| a毛片在线免费观看| 亚洲中文字幕成人在线| 美女羞羞视频免费网站| 精品国产免费观看一区| 亚洲看片无码在线视频| 美女网站免费福利视频| 亚洲精品不卡视频| 午夜免费福利小电影| 久久精品国产亚洲av麻| 十八禁视频在线观看免费无码无遮挡骂过 | 免费吃奶摸下激烈视频| 亚洲а∨精品天堂在线| 国产色爽女小说免费看| 亚洲精品无AMM毛片| 女性自慰aⅴ片高清免费| 国产人成亚洲第一网站在线播放| 日韩av无码成人无码免费| 亚洲人成综合网站7777香蕉| 在线观看免费av网站| 91亚洲一区二区在线观看不卡| a级毛片在线免费看| 亚洲一区二区三区免费| 一级黄色免费大片| 相泽亚洲一区中文字幕| 国产精品免费在线播放| 国产亚洲精品成人AA片新蒲金 | 免费黄色小视频网站| 亚洲精品无码少妇30P| 午夜影视在线免费观看| 亚洲av成人无码网站…| 免费真实播放国产乱子伦| 免费一级毛suv好看的国产网站| 亚洲国产av一区二区三区| 国产97视频人人做人人爱免费| 亚洲桃色AV无码|