你用對synchronized了嗎

最近遇到一個crash問題排惨,是關(guān)于線程同步鎖的纵搁,檢查代碼的時候發(fā)現(xiàn)方法已經(jīng)使用synchronized同步了,為什么還會出現(xiàn)該異常呢?

就想是不是synchronized使用的不對呢亭珍?查了些資料發(fā)現(xiàn)好像synchronized真用錯了铛纬!

我們先看一下synchronized的官方定義:

 synchronized Java語言的關(guān)鍵字章喉,可用來給對象和方法或者代碼塊加鎖梅肤,當它鎖定一個方法或者一個代碼塊的時候,同一時刻最多只有一個線程執(zhí)行這段代碼沐序。

我們先來看一段代碼

public class Test {
    class DB {
        private synchronized void query() {
            System.out.println("開始查詢");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("查詢結(jié)束");

        }
    }

    private static Runnable myRunnable = new Runnable() {

        @Override
        public void run() {
            DB db = new Test().new DB();
            db.query();
        }
    };

    public static void main(String[] args) throws Exception {
        Thread thread1 = new Thread(myRunnable);
        thread1.start();
        Thread thread2 = new Thread(myRunnable);
        thread2.start();
    }
}

我們看下輸出結(jié)果

開始查詢
開始查詢
查詢結(jié)束
查詢結(jié)束

咦 我的方法已經(jīng)加了synchronized了琉用,為什么還是用兩個線程同時執(zhí)行了query方法呢?是不是synchronized加錯地方了呢?

我們改下代碼 把query方法前面的synchronized 去掉 放到方法里面去

private void query() {
        synchronized (this) {
            System.out.println("開始查詢");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("查詢結(jié)束");
        }
    }

這樣我鎖住這個代碼塊應(yīng)該就沒問題了吧策幼!我們來看下運行結(jié)果

開始查詢
開始查詢
查詢結(jié)束
查詢結(jié)束

恩邑时?怎么還是兩個線程同時執(zhí)行了query方法呢?

 想一個問題 synchronized 到底鎖住的是方法,是代碼塊還是對象特姐?

來看下面代碼

private void query() {
        synchronized (DB.class) {
            System.out.println("開始查詢");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("查詢結(jié)束");

        }
    }
}

把上面的的synchronized (this)改成 synchronized (DB.class) 晶丘,執(zhí)行程序看下結(jié)果
開始查詢
查詢結(jié)束
開始查詢
查詢結(jié)束

終于輸出了我們期望的結(jié)果。

 說下上面的問題唐含,synchronized 鎖住的是什么浅浮?
 synchronized 鎖住的是括號里面的對象!

我們回頭看下第一段代碼把synchronized 加到方法前面捷枯,怎么能輸出正確的結(jié)果滚秩?我們改下代碼

 public class Test {
class DB {
    private synchronized void query() {
            System.out.println("開始查詢");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("查詢結(jié)束");
    }
}
private static  DB db = new Test().new DB();
private static Runnable myRunnable = new Runnable() {

    public void run() {
        db.query();
    }
};

public static void main(String[] args) throws Exception {
    Thread thread1 = new Thread(myRunnable);
    thread1.start();
    Thread thread2 = new Thread(myRunnable);
    thread2.start();
        }
}

執(zhí)行程序 看下輸出結(jié)果

開始查詢
查詢結(jié)束
開始查詢
查詢結(jié)束

程序正常輸出

 當synchronized加到方法前面時,當有多個線程同時訪問 ”同一個對象” 的synchronized方法時淮捆,一個時間內(nèi)只能有一個線程得到執(zhí)行叔遂。另一個線程必須等待當前線程執(zhí)行完這個方法才能執(zhí)行。
  synchronized有風(fēng)險争剿,要用需謹慎啊痊末!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蚕苇,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子凿叠,更是在濱河造成了極大的恐慌涩笤,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盒件,死亡現(xiàn)場離奇詭異蹬碧,居然都是意外死亡,警方通過查閱死者的電腦和手機炒刁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進店門恩沽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人翔始,你說我怎么就攤上這事罗心±锊” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵渤闷,是天一觀的道長疾瓮。 經(jīng)常有香客問我,道長飒箭,這世上最難降的妖魔是什么狼电? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮弦蹂,結(jié)果婚禮上肩碟,老公的妹妹穿的比我還像新娘。我一直安慰自己盈匾,他們只是感情好腾务,可當我...
    茶點故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著削饵,像睡著了一般岩瘦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上窿撬,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天启昧,我揣著相機與錄音,去河邊找鬼劈伴。 笑死密末,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的跛璧。 我是一名探鬼主播严里,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼追城!你這毒婦竟也來了刹碾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤座柱,失蹤者是張志新(化名)和其女友劉穎迷帜,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體色洞,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡戏锹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了火诸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锦针。...
    茶點故事閱讀 38,747評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出伞插,到底是詐尸還是另有隱情割粮,我是刑警寧澤,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布媚污,位于F島的核電站舀瓢,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏耗美。R本人自食惡果不足惜京髓,卻給世界環(huán)境...
    茶點故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望商架。 院中可真熱鬧堰怨,春花似錦、人聲如沸蛇摸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽赶袄。三九已至揽涮,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間饿肺,已是汗流浹背蒋困。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留敬辣,地道東北人雪标。 一個月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像溉跃,于是被迫代替她去往敵國和親村刨。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,658評論 2 350

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法撰茎,類相關(guān)的語法烹困,內(nèi)部類的語法,繼承相關(guān)的語法乾吻,異常的語法,線程的語...
    子非魚_t_閱讀 31,602評論 18 399
  • 從三月份找實習(xí)到現(xiàn)在拟蜻,面了一些公司绎签,掛了不少,但最終還是拿到小米酝锅、百度诡必、阿里、京東、新浪爸舒、CVTE蟋字、樂視家的研發(fā)崗...
    時芥藍閱讀 42,218評論 11 349
  • Java8張圖 11、字符串不變性 12扭勉、equals()方法鹊奖、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,697評論 0 11
  • 有些人會一直刻在記憶里的涂炎,即使忘記了他的聲音忠聚,忘記了他的笑容,忘記了他的臉唱捣,但是每當想起他時的那種感受两蟀,是永遠都不...
    Uynahhruzuy閱讀 165評論 0 0
  • 所有的相遇,都是上天注定 你選擇加入大慈 今生與我們成為家人 是上天對你最好的安排 當你愿意跟隨大慈一起 改變生活...
    A阿成閱讀 216評論 0 0