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

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

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

    隨筆-200  評(píng)論-148  文章-15  trackbacks-0

    synchronized的作用?
    一、同步方法
    public synchronized void methodAAA(){

    //….

    }
    鎖定的是調(diào)用這個(gè)同步方法的對(duì)象

    測試:
    a、不使用這個(gè)關(guān)鍵字修飾方法,兩個(gè)線程調(diào)用同一個(gè)對(duì)象的這個(gè)方法。
    目標(biāo)類:

    1 public ? class ?TestThread? {
    2 ???? public ?? void ?execute() {?? // synchronized,未修飾
    3 ???????? for ( int ?i = 0 ;i < 100 ;i ++ ) {
    4 ????????????System.out.println(i);
    5 ????????}
    ????
    6 ????}

    7 }


    線程類:

    1 public ? class ?ThreadA? implements ?Runnable {
    2 ????TestThread?test = null ;
    3 ???? public ?ThreadA(TestThread?pTest) {?? // 對(duì)象有外部引入,這樣保證是同一個(gè)對(duì)象
    4 ????????test = pTest;
    5 ????}

    6 ???? public ? void ?run()? {
    7 ????????test.execute();
    8 ????}

    9 }

    調(diào)用:
    1TestThread?test=new?TestThread();
    2Runnable?runabble=new?ThreadA(test);
    3Thread?a=new?Thread(runabble,"A");????????????????
    4a.start();
    5Thread?b=new?Thread(runabble,"B");
    6b.start();


    結(jié)果:
    輸出的數(shù)字交錯(cuò)在一起。說明不是同步的,兩個(gè)方法在不同的線程中是異步調(diào)用的。

    b、修改目標(biāo)類,增加synchronized修飾

    1public?class?TestThread?{
    2????public?synchronized??void?execute(){??//synchronized修飾
    3????????for(int?i=0;i<100;i++){
    4????????????System.out.println(i);
    5????????}
    ????
    6????}

    7}


    結(jié)果:
    輸出的數(shù)字是有序的,首先輸出A的數(shù)字,然后是B,說明是同步的,雖然是不同的線程,但兩個(gè)方法是同步調(diào)用的。
    注意:上面雖然是兩個(gè)不同的線程,但是是同一個(gè)實(shí)例對(duì)象。下面使用不同的實(shí)例對(duì)象進(jìn)行測試。

    c、每個(gè)線程都有獨(dú)立的TestThread對(duì)象。
    目標(biāo)類:

    1public?class?TestThread?{
    2????public?synchronized?void?execute(){??//synchronized修飾
    3????????for(int?i=0;i<100;i++){
    4????????????System.out.println(i);
    5????????}
    ????
    6????}

    7}

    線程類:
    1public?class?ThreadA?implements?Runnable{
    2????public?void?run()?{
    3????????TestThread?test=new?TestThread();
    4????????test.execute();
    5????}

    6}

    7

    調(diào)用:
    1Runnable?runabble=new?ThreadA();
    2Thread?a=new?Thread(runabble,"A");????????????????
    3a.start();
    4Thread?b=new?Thread(runabble,"B");
    5b.start();


    結(jié)果:
    輸出的數(shù)字交錯(cuò)在一起。說明雖然增加了synchronized 關(guān)鍵字來修飾方法,但是不同的線程調(diào)用各自的對(duì)象實(shí)例,兩個(gè)方法仍然是異步的。

    引申:
    對(duì)于這種多個(gè)實(shí)例,要想實(shí)現(xiàn)同步即輸出的數(shù)字是有序并且按線程先后順序輸出,我們可以增加一個(gè)靜態(tài)變量,對(duì)它進(jìn)行加鎖(后面將說明鎖定的對(duì)象)。

    修改目標(biāo)類:

    ?1public?class?TestThread?{
    ?2????private?static?Object?lock=new?Object();?//必須是靜態(tài)的。
    ?3????public??void?execute(){
    ?4????????synchronized(lock){
    ?5????????????for(int?i=0;i<100;i++){
    ?6????????????????System.out.println(i);
    ?7????????????}
    ????
    ?8????????}

    ?9????}

    10}

    二、同步代碼塊

    1public?void?method(SomeObject?so){
    2????synchronized(so)
    3???????//…..
    4????}

    5}

    鎖定一個(gè)對(duì)象,其實(shí)鎖定的是該對(duì)象的引用(object reference)
    誰拿到這個(gè)鎖誰就可以運(yùn)行它所控制的那段代碼。當(dāng)有一個(gè)明確的對(duì)象作為鎖時(shí),就可以按上面的代碼寫程序,但當(dāng)沒有明確的對(duì)象作為鎖,只是想讓一段代碼同步時(shí),可以創(chuàng)建一個(gè)特殊的instance變量(它必須是一個(gè)對(duì)象)來充當(dāng)鎖(上面的解決方法就是增加了一個(gè)狀態(tài)鎖)。

    a、鎖定一個(gè)對(duì)象,它不是靜態(tài)的
    private byte[] lock = new byte[0]; // 特殊的instance變量
    目標(biāo)類:

    ?1public?class?TestThread?{
    ?2????private?Object?lock=new?Object();?
    ?3????public??void?execute(){
    ?4????????synchronized(lock){??//增加了個(gè)鎖,鎖定了對(duì)象lock,在同一個(gè)類實(shí)例中,是線程安全的,但不同的實(shí)例還是不安全的。
    ?5
    ?6因?yàn)椴煌膶?shí)例有不同對(duì)象鎖lock
    ?7????????????for(int?i=0;i<100;i++){
    ?8????????????????System.out.println(i);
    ?9????????????}
    ????
    10????????}

    11????}

    12}
    ??


    其實(shí)上面鎖定一個(gè)方法,等同于下面的:

    1public?void?execute(){??
    2????synchronized(this){???//同步的是當(dāng)然對(duì)象
    3????????for(int?i=0;i<100;i++){
    4????????????System.out.println(i);
    5????????}
    ????
    6????}

    7}

    b、鎖定一個(gè)對(duì)象或方法,它是靜態(tài)的
    這樣鎖定,它鎖定的是對(duì)象所屬的類
    public synchronized? static void execute(){
    ??? //...
    }
    等同于

    1public?class?TestThread?{
    2????public?static?void?execute(){
    3????????synchronized(TestThread.class){
    4????????????//
    5????????}

    6????}

    7}

    測試:

    目標(biāo)類:

    ?1public?class?TestThread?{
    ?2????private?static?Object?lock=new?Object();
    ?3????public?synchronized?static?void?execute(){??//同步靜態(tài)方法
    ?4????????for(int?i=0;i<100;i++){
    ?5????????????System.out.println(i);
    ?6????????}
    ????
    ?7????}

    ?8????public?static?void?execute1(){
    ?9????????for(int?i=0;i<100;i++){
    10????????????System.out.println(i);
    11????????}
    ????
    12????}

    13????public?void?test(){
    14????????execute();?????//輸出是有序的,說明是同步的
    15????????//execute1();??//輸出是無須的,說明是異步的
    16????}

    17}

    線程類:調(diào)用不同的方法,于是建立了兩個(gè)線程類

    ?1public?class?ThreadA?implements?Runnable{
    ?2????public?void?run()?{
    ?3????????TestThread.execute();//調(diào)用同步靜態(tài)方法
    ?4????}

    ?5}

    ?6public?class?ThreadB?implements?Runnable{
    ?7????public?void?run()?{
    ?8????????TestThread?test=new?TestThread();
    ?9????????test.test();//調(diào)用非同步非靜態(tài)方法
    10????}

    11}

    調(diào)用:

    1Runnable?runabbleA=new?ThreadA();
    2Thread?a=new?Thread(runabbleA,"A");????????????????
    3a.start();
    4Runnable?runabbleB=new?ThreadB();
    5Thread?b=new?Thread(runabbleB,"B");????????????????
    6b.start();

    注意:
    1、用synchronized 來鎖定一個(gè)對(duì)象的時(shí)候,如果這個(gè)對(duì)象在鎖定代碼段中被修改了,則這個(gè)鎖也就消失了。看下面的實(shí)例:

    目標(biāo)類:

    ?1public?class?TestThread?{
    ?2?????private?static?final?class?TestThreadHolder?{
    ?3????????????private?static?TestThread?theSingleton?=?new?TestThread();
    ?4????????????public?static?TestThread?getSingleton()?{
    ?5????????????????return?theSingleton;
    ?6????????????}

    ?7????????????private?TestThreadHolder()?{
    ?8????????????}

    ?9????????}

    10?????
    11????private?Vector?ve?=null;
    12????private?Object?lock=new?Object();
    13????private?TestThread(){
    14????????ve=new?Vector();
    15????????initialize();
    16????}

    17????public?static?TestThread?getInstance(){
    18????????return?TestThreadHolder.getSingleton();
    19????}

    20????private?void?initialize(){
    21????????for(int?i=0;i<100;i++){
    22????????????ve.add(String.valueOf(i));
    23????????}

    24????}

    25????public?void?reload(){
    26????????synchronized(lock){
    27????????????ve=null;????????????
    28????????????ve=new?Vector();
    29????????????????????????//lock="abc";?
    30????????????for(int?i=0;i<100;i++){
    31????????????????ve.add(String.valueOf(i));
    32????????????}

    33????????}

    34????????System.out.println("reload?end");
    35????}

    36????
    37????public?boolean?checkValid(String?str){
    38????????synchronized(lock){
    39????????????System.out.println(ve.size());
    40????????????return?ve.contains(str);
    41????????}

    42????}

    43}

    說明:在reload和checkValid方法中都增加了synchronized關(guān)鍵字,對(duì)lock對(duì)象進(jìn)行加鎖。在不同線程中對(duì)同一個(gè)對(duì)象實(shí)例分別調(diào)用reload和checkValid方法。
    在reload方法中,不修改lock對(duì)象即注釋lock="abc"; ,結(jié)果在控制臺(tái)輸出reload end后才輸出100。說明是同步調(diào)用的。
    如果在reload方法中修改lock對(duì)象即去掉注釋,結(jié)果首先輸出了一個(gè)數(shù)字(當(dāng)前ve的大小),然后輸出reload end。說明是異步調(diào)用的。

    2、單例模式中對(duì)多線程的考慮

    ?1public?class?TestThread?{
    ?2?????private?static?final?class?TestThreadHolder?{
    ?3????????????private?static?TestThread?theSingleton?=?new?TestThread();
    ?4????????????public?static?TestThread?getSingleton()?{
    ?5????????????????return?theSingleton;
    ?6????????????}

    ?7????????????private?TestThreadHolder()?{
    ?8????????????}

    ?9????????}

    10????private?Vector?ve?=null;
    11????private?Object?lock=new?Object();
    12????private?TestThread(){
    13????????ve=new?Vector();
    14????????initialize();
    15????}

    16????public?static?TestThread?getInstance(){
    17????????return?TestThreadHolder.getSingleton();
    18????}

    19????????'''
    20}

    說明:增加了一個(gè)內(nèi)部類,在內(nèi)部類中申明一個(gè)靜態(tài)的對(duì)象,實(shí)例化該單例類,初始化的數(shù)據(jù)都在單例類的構(gòu)造函數(shù)中進(jìn)行。這樣保證了多個(gè)實(shí)例同時(shí)訪問的時(shí)候,初始化的數(shù)據(jù)都已經(jīng)成功初始化了。

    總結(jié):
    A. 無論synchronized關(guān)鍵字加在方法上還是對(duì)象上,它取得的鎖都是對(duì)象,而不是把一段代碼或函數(shù)當(dāng)作鎖,所以首先應(yīng)知道需要加鎖的對(duì)象
    B.每個(gè)對(duì)象只有一個(gè)鎖(lock)與之相關(guān)聯(lián)。
    C.實(shí)現(xiàn)同步是要很大的系統(tǒng)開銷作為代價(jià)的,甚至可能造成死鎖,所以盡量避免無謂的同步控制
    posted on 2008-08-06 14:44 無聲 閱讀(426) 評(píng)論(0)  編輯  收藏 所屬分類: 職場生活
    主站蜘蛛池模板: 亚洲高清国产拍精品青青草原| 99爱视频99爱在线观看免费| 7723日本高清完整版免费| 亚洲gv白嫩小受在线观看| jizz在线免费观看| 亚洲色偷偷综合亚洲AVYP| 一级成人a做片免费| 综合亚洲伊人午夜网 | 亚洲黄色免费观看| 亚洲视频小说图片| 中文字幕无码播放免费| 亚洲va久久久久| 国产大片91精品免费观看男同| 亚洲国产精品日韩av不卡在线| 午夜一级免费视频| 免费精品国产自产拍在线观看 | 久久最新免费视频| 亚洲国产成人久久精品动漫| 91老湿机福利免费体验| 国产精品久久亚洲不卡动漫| 99久久免费精品国产72精品九九 | 亚洲人成电影青青在线播放| 国产在线国偷精品产拍免费| 久久精品国产亚洲AV未满十八| 国产成人高清亚洲| 免费国产黄网站在线观看| 日韩亚洲不卡在线视频中文字幕在线观看| 免费黄色大片网站| 精品人妻系列无码人妻免费视频| 亚洲欧洲日韩不卡| 热99re久久免费视精品频软件 | 国产亚洲蜜芽精品久久| 国产亚洲色婷婷久久99精品91| 99精品视频在线视频免费观看| 亚洲色大18成人网站WWW在线播放| 国产成人无码免费视频97| 久久免费线看线看| 亚洲欧洲无卡二区视頻| 亚洲人成人77777网站| 91情侣在线精品国产免费| 一级毛片完整版免费播放一区|