Java線程同步:synchronized鎖住的是代碼還是對象

Java中徐钠,synchronized關(guān)鍵字是用來控制線程同步的值依,就是在多線程的環(huán)境下良狈,控制synchronized代碼段不被多個(gè)線程同時(shí)執(zhí)行昭卓。synchronized既可以加在一段代碼上张足,也可以加在方法上触创。
關(guān)鍵是,不要認(rèn)為給方法或者代碼段加上synchronized就萬事大吉为牍,看下面一段代碼:

class Sync {  
  
    public synchronized void test() {  
        System.out.println("test開始..");  
        try {  
            Thread.sleep(1000);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        System.out.println("test結(jié)束..");  
    }  
}  
  
class MyThread extends Thread {  
  
    public void run() {  
        Sync sync = new Sync();  
        sync.test();  
    }  
}  
  
public class Main {  
  
    public static void main(String[] args) {  
        for (int i = 0; i < 3; i++) {  
            Thread thread = new MyThread();  
            thread.start();  
        }  
    }  
}  

運(yùn)行結(jié)果:
test開始..
test開始..
test開始..
test結(jié)束..
test結(jié)束..
test結(jié)束..

可以看出來哼绑,上面的程序起了三個(gè)線程,同時(shí)運(yùn)行Sync類中的test()方法碉咆,雖然test()方法加上了synchronized抖韩,但是還是同時(shí)運(yùn)行起來,貌似synchronized沒起作用疫铜。

將test()方法上的synchronized去掉茂浮,在方法內(nèi)部加上synchronized(this):


public void test() {  
    synchronized(this){  
        System.out.println("test開始..");  
        try {  
            Thread.sleep(1000);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
        System.out.println("test結(jié)束..");  
    }  
}  

運(yùn)行結(jié)果:
test開始..
test開始..
test開始..
test結(jié)束..
test結(jié)束..
test結(jié)束..

一切還是這么平靜,沒有看到synchronized起到作用壳咕。

實(shí)際上席揽,synchronized(this)以及非static的synchronized方法(至于static synchronized方法請往下看),只能防止多個(gè)線程同時(shí)執(zhí)行同一個(gè)對象的同步代碼段谓厘。

回到本文的題目上:synchronized鎖住的是代碼還是對象幌羞。答案是:synchronized鎖住的是括號里的對象,而不是代碼竟稳。對于非static的synchronized方法属桦,鎖的就是對象本身也就是this熊痴。

當(dāng)synchronized鎖住一個(gè)對象后,別的線程如果也想拿到這個(gè)對象的鎖聂宾,就必須等待這個(gè)線程執(zhí)行完成釋放鎖愁拭,才能再次給對象加鎖,這樣才達(dá)到線程同步的目的亏吝。即使兩個(gè)不同的代碼段岭埠,都要鎖同一個(gè)對象,那么這兩個(gè)代碼段也不能在多線程環(huán)境下同時(shí)運(yùn)行蔚鸥。

所以我們在用synchronized關(guān)鍵字的時(shí)候惜论,能縮小代碼段的范圍就盡量縮小,能在代碼段上加同步就不要再整個(gè)方法上加同步止喷。這叫減小鎖的粒度馆类,使代碼更大程度的并發(fā)。原因是基于以上的思想弹谁,鎖的代碼段太長了乾巧,別的線程是不是要等很久,等的花兒都謝了预愤。當(dāng)然這段是題外話沟于,與本文核心思想并無太大關(guān)聯(lián)。

再看上面的代碼植康,每個(gè)線程中都new了一個(gè)Sync類的對象旷太,也就是產(chǎn)生了三個(gè)Sync對象,由于不是同一個(gè)對象销睁,所以可以多線程同時(shí)運(yùn)行synchronized方法或代碼段供璧。

為了驗(yàn)證上述的觀點(diǎn),修改一下代碼冻记,讓三個(gè)線程使用同一個(gè)Sync的對象睡毒。

class MyThread extends Thread {  
  
    private Sync sync;  
  
    public MyThread(Sync sync) {  
        this.sync = sync;  
    }  
  
    public void run() {  
        sync.test();  
    }  
}  
  
public class Main {  
  
    public static void main(String[] args) {  
        Sync sync = new Sync();  
        for (int i = 0; i < 3; i++) {  
            Thread thread = new MyThread(sync);  
            thread.start();  
        }  
    }  
}  

運(yùn)行結(jié)果:
test開始..
test結(jié)束..
test開始..
test結(jié)束..
test開始..
test結(jié)束..

可以看到,此時(shí)的synchronized就起了作用冗栗。

那么演顾,如果真的想鎖住這段代碼,要怎么做贞瞒?也就是偶房,如果還是最開始的那段代碼趁曼,每個(gè)線程new一個(gè)Sync對象军浆,怎么才能讓test方法不會被多線程執(zhí)行。

解決也很簡單挡闰,只要鎖住同一個(gè)對象不就行了乒融。例如掰盘,synchronized后的括號中鎖同一個(gè)固定對象,這樣就行了赞季。這樣是沒問題愧捕,但是,比較多的做法是讓synchronized鎖這個(gè)類對應(yīng)的Class對象申钩。

class Sync {  
  
    public void test() {  
        synchronized (Sync.class) {  
            System.out.println("test開始..");  
            try {  
                Thread.sleep(1000);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
            System.out.println("test結(jié)束..");  
        }  
    }  
}  
  
class MyThread extends Thread {  
  
    public void run() {  
        Sync sync = new Sync();  
        sync.test();  
    }  
}  
  
public class Main {  
  
    public static void main(String[] args) {  
        for (int i = 0; i < 3; i++) {  
            Thread thread = new MyThread();  
            thread.start();  
        }  
    }  
}  

運(yùn)行結(jié)果:
test開始..
test結(jié)束..
test開始..
test結(jié)束..
test開始..
test結(jié)束..
上面代碼用synchronized(Sync.class)實(shí)現(xiàn)了全局鎖的效果次绘。

最后說說static synchronized方法,static方法可以直接類名加方法名調(diào)用撒遣,方法中無法使用this邮偎,所以它鎖的不是this,而是類的Class對象义黎,所以禾进,static synchronized方法也相當(dāng)于全局鎖,相當(dāng)于鎖住了代碼段廉涕。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末泻云,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子狐蜕,更是在濱河造成了極大的恐慌宠纯,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件层释,死亡現(xiàn)場離奇詭異征椒,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)湃累,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進(jìn)店門勃救,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人治力,你說我怎么就攤上這事蒙秒。” “怎么了宵统?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵晕讲,是天一觀的道長。 經(jīng)常有香客問我马澈,道長瓢省,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任痊班,我火速辦了婚禮勤婚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘涤伐。我一直安慰自己馒胆,他們只是感情好缨称,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著祝迂,像睡著了一般睦尽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上型雳,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天当凡,我揣著相機(jī)與錄音,去河邊找鬼纠俭。 笑死宁玫,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的柑晒。 我是一名探鬼主播欧瘪,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼匙赞!你這毒婦竟也來了佛掖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤涌庭,失蹤者是張志新(化名)和其女友劉穎芥被,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坐榆,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拴魄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了席镀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片匹中。...
    茶點(diǎn)故事閱讀 40,498評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖豪诲,靈堂內(nèi)的尸體忽然破棺而出顶捷,到底是詐尸還是另有隱情,我是刑警寧澤屎篱,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布服赎,位于F島的核電站,受9級特大地震影響交播,放射性物質(zhì)發(fā)生泄漏重虑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一秦士、第九天 我趴在偏房一處隱蔽的房頂上張望缺厉。 院中可真熱鬧,春花似錦伍宦、人聲如沸芽死。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽关贵。三九已至,卻和暖如春卖毁,著一層夾襖步出監(jiān)牢的瞬間揖曾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工亥啦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留炭剪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓翔脱,卻偏偏與公主長得像奴拦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子届吁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,507評論 2 359

推薦閱讀更多精彩內(nèi)容