synchronized 用法

一啊央、代碼示例

1.synchronized修飾普通方法

synchronized修飾普通代碼,加鎖對象為調(diào)用這個方法的對象

public class SynchronizedTest {

    private int age;

    public synchronized int getAge() throws InterruptedException {
        Thread.sleep(10000);
        System.out.println(Thread.currentThread().getName()+"**"+System.currentTimeMillis());
        return age;
    }

    public static void main(String []args){
        SynchronizedTest synchronizedTest = new  SynchronizedTest();
        Thread thread1 = new Thread("t1"){
            @Override
            public void run(){
                try {
                    synchronizedTest.getAge();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        Thread thread2 = new Thread("t2"){
            @Override
            public void run(){
                try {
                    synchronizedTest.getAge();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        thread1.start();
        thread2.start();
    }
    
}

因?yàn)?個線程調(diào)用getAge()方法的都是同一個對象synchronizedTest 幢码,所以2個線程是串行進(jìn)行,thread2會等待thread1
運(yùn)行結(jié)果如下

t1**1561547808386
t2**1561547818390

這里說一點(diǎn):最近在項(xiàng)目中洲脂,發(fā)現(xiàn)有人寫了這樣一段代碼

synchronized (jedisPool) {
    if(jedisPool == null){
        initialPool(); 
    }
}

大家發(fā)現(xiàn)里面錯誤了么
這里強(qiáng)調(diào)一點(diǎn)竹勉,因?yàn)镴ava對象只有一個內(nèi)置鎖裹虫,synchronized 會在這個內(nèi)置鎖進(jìn)行加鎖肿嘲,我們平時定義對象為空類似

Object ob = null;

這個只是把對象指向一個空引用,并沒有任何初始化筑公,空在Java中是一種特殊類型雳窟,并不是對象。
如果代碼中判斷synchronized 加鎖對象為空應(yīng)該在synchronized 之前作出判斷,如果加鎖對象為空會報空指針異常封救。
這里我們再思考一個問題拇涤,如果多線程訪問同一對象的不同的被synchronized修飾的普通方法會發(fā)生什么

public class SynchronizedTest6 {

    public synchronized void getAge() throws InterruptedException {
        Thread.sleep(10000);
        System.out.println(Thread.currentThread().getName()+"**"+System.currentTimeMillis());
    }

    public synchronized void test() throws InterruptedException {
        Thread.sleep(10000);
        System.out.println(Thread.currentThread().getName()+"**"+System.currentTimeMillis());
    }

    public static void main(String []args){
        SynchronizedTest6 synchronizedTest6 = new  SynchronizedTest6();
        Thread thread1 = new Thread("t1"){
            @Override
            public void run(){
                try {
                    synchronizedTest6.getAge();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        Thread thread2 = new Thread("t2"){
            @Override
            public void run(){
                try {
                    synchronizedTest6.test();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        thread1.start();
        thread2.start();
    }
}

因?yàn)閟ynchronized是加在對象內(nèi)置鎖上所以結(jié)果顯而易見,多線程會串行進(jìn)行,結(jié)果如下

t1**1561745488571
t2**1561745498572

2.synchronized修飾靜態(tài)方法

synchronized修飾靜態(tài)方法誉结,鎖會發(fā)生在這個靜態(tài)方法類上,多個線程訪問同一靜態(tài)方法會串行執(zhí)行

public class SynchronizedTest3 implements Runnable{

    @Override
    public void run() {
        try {
            test();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static synchronized void test() throws InterruptedException {
        Thread.sleep(10000);
        System.out.println(Thread.currentThread().getName()+System.currentTimeMillis());
    }

    public static void main(String []args){
        SynchronizedTest3 synchronizedTest3 = new SynchronizedTest3();
        SynchronizedTest3 synchronizedTest31 = new SynchronizedTest3();
        Thread thread1 = new Thread(synchronizedTest3);
        Thread thread2 = new Thread(synchronizedTest31);
        thread1.start();
        thread2.start();

    }
}

運(yùn)行結(jié)果如下

Thread-01561744252006
Thread-11561744262008

3.synchronized修飾類

效果類同synchronized修飾靜態(tài)方法

public class SynchronizedTest4 implements Runnable{

    @Override
    public void run() {
        try {
            test();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public  void test() throws InterruptedException {
        synchronized (SynchronizedTest4.class){
            Thread.sleep(10000);
            System.out.println(Thread.currentThread().getName()+System.currentTimeMillis());
        }

    }

    public static void main(String []args){
         SynchronizedTest4 synchronizedTest = new SynchronizedTest4();
        SynchronizedTest4 synchronizedTest_ = new SynchronizedTest4();
        Thread thread1 = new Thread(synchronizedTest);
        Thread thread2 = new Thread(synchronizedTest_);
        thread1.start();
        thread2.start();

    }
}
Thread-11561744702391
Thread-01561744712400

二鹅士、原理

在這里我們反編譯下class,先看下字節(jié)碼生成惩坑,這里推薦大家使用idea的插件jclasslib bytecode viewer查看字節(jié)碼

image.png

同步代碼塊其實(shí)是通過monitorenter和monitorexit指令實(shí)現(xiàn)的掉盅,我們前面說了每個對象都有一把內(nèi)置鎖,這個鎖其實(shí)是monitor(也被成為監(jiān)視器鎖)以舒,同一時間只能有一個對象獲取到monitor趾痘,monitorenter指令會嘗試獲取monitor,而monitorexit會釋放掉monitorexit蔓钟。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末永票,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子滥沫,更是在濱河造成了極大的恐慌侣集,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件佣谐,死亡現(xiàn)場離奇詭異肚吏,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)狭魂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進(jìn)店門罚攀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人雌澄,你說我怎么就攤上這事斋泄。” “怎么了镐牺?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵炫掐,是天一觀的道長。 經(jīng)常有香客問我睬涧,道長募胃,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任畦浓,我火速辦了婚禮痹束,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘讶请。我一直安慰自己祷嘶,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著论巍,像睡著了一般烛谊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嘉汰,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天丹禀,我揣著相機(jī)與錄音,去河邊找鬼郑现。 笑死湃崩,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的接箫。 我是一名探鬼主播攒读,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼辛友!你這毒婦竟也來了薄扁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤废累,失蹤者是張志新(化名)和其女友劉穎邓梅,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體邑滨,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡日缨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了掖看。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片匣距。...
    茶點(diǎn)故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖哎壳,靈堂內(nèi)的尸體忽然破棺而出毅待,到底是詐尸還是另有隱情,我是刑警寧澤归榕,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布尸红,位于F島的核電站,受9級特大地震影響刹泄,放射性物質(zhì)發(fā)生泄漏外里。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一特石、第九天 我趴在偏房一處隱蔽的房頂上張望级乐。 院中可真熱鬧,春花似錦县匠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽贼穆。三九已至,卻和暖如春兰粉,著一層夾襖步出監(jiān)牢的瞬間故痊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工玖姑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留愕秫,地道東北人。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓焰络,卻偏偏與公主長得像戴甩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子闪彼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評論 2 355

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

  • synchronized是Java中的關(guān)鍵字甜孤,是一種同步鎖。它修飾的對象有以下幾種: 修飾一個代碼塊畏腕,被修飾的代碼...
    境里婆娑閱讀 378評論 0 0
  • 互斥鎖:當(dāng)一線程進(jìn)入synchronized修飾的代碼塊或者方法缴川,其它線程等待,知道鎖被釋放描馅;內(nèi)置鎖:對象鎖把夸,每個...
    懶眉閱讀 492評論 0 1
  • synchronized是Java中的關(guān)鍵字,是一種同步鎖铭污。它修飾的對象有以下幾種: 修飾一個代碼塊恋日,被修飾的代碼...
    4e70992f13e7閱讀 359評論 0 1
  • 雖然網(wǎng)上關(guān)于Java并發(fā)、多線程的文章已是不勝枚舉况凉,但是讀起來總感覺晦澀且千篇一律谚鄙,不是你轉(zhuǎn)載我,就是我復(fù)制你刁绒。在...
    Hystrix閱讀 467評論 0 3
  • 1 拿什么拯救你我的肥胖兒子知市,寫下這個題目的時候傻盟,做為一個母親,我的感覺是有一點(diǎn)悲涼嫂丙,是為天下為自己的孩子充滿了焦...
    彧婠九尾貓閱讀 816評論 2 3