synchronized關(guān)鍵字

多線程并發(fā)訪問同步問題磕潮。
java中每個(gè)對象編譯后的字節(jié)碼中翠胰,有個(gè)頭部。
頭部存儲(chǔ)著hashcode自脯,對象垃圾回收的年齡之景,還有就是內(nèi)部鎖信息。

線程間互斥同步就是使用synchronized實(shí)現(xiàn)的膏潮,synchronized關(guān)鍵字锻狗,在編譯后,會(huì)在同步塊的前后焕参,生成monitor enter和monitor exit字節(jié)碼指令轻纪。關(guān)鍵字鎖住的是對象的鎖。

synchronized關(guān)鍵字加鎖的過程是怎樣叠纷?

  1. java代碼碰到synchronized關(guān)鍵字刻帚,在編譯后,會(huì)在同步塊的前后涩嚣,生成monitor enter和monitor exit字節(jié)碼指令崇众。
  2. 線程碰到monitor enter指令后,會(huì)先判斷航厚,這個(gè)對象的鎖有沒有被別的線程占用顷歌,如果沒有,就占用鎖幔睬,并在鎖的計(jì)數(shù)器上+1(鎖是可以被同一個(gè)線程重入的眯漩,所以不會(huì)存在自己死鎖的情況)。
  3. 如果發(fā)現(xiàn)對象的鎖已經(jīng)被占用麻顶,線程就阻塞等待赦抖。
  4. 當(dāng)拿到鎖的線程執(zhí)行到monitor exit時(shí)舱卡,鎖的計(jì)數(shù)器-1,當(dāng)對象的鎖計(jì)數(shù)器為0時(shí)摹芙,表示對象的鎖被釋放了灼狰。別的線程可以去拿到鎖,進(jìn)入同步代碼塊了浮禾。

java的線程使用synchronized關(guān)鍵字同步相較于,其他的一些操作份汗,是很重的耗性能的操作盈电。因?yàn)樵诨コ獾却龁拘训牟僮髦校琷ava線程底層是要跟操作系統(tǒng)內(nèi)核線程去映射的杯活。所以開發(fā)人員在使用的時(shí)候應(yīng)該特別小心哈匆帚。

因?yàn)楹男阅芪兀砸灿辛讼鄳?yīng)的優(yōu)化的鎖的概念嚎幸。要根據(jù)場景去使用設(shè)置寄猩。
對象的鎖有重度鎖,輕量級鎖替废,偏向鎖(大概的實(shí)現(xiàn)思路椎镣,就跟數(shù)據(jù)庫的樂觀鎖是一個(gè)概念)兽赁。

synchronized關(guān)鍵字可以作用在哪些地方,分別的作用范圍是怎樣剪况?
代碼塊蒲跨,方法或悲,靜態(tài)方法堪唐,類

  1. 作用在代碼塊時(shí)
    結(jié)論:synchronized代碼塊只會(huì)影響同一對象(因?yàn)殒i的是對象)的所有synchronized代碼塊的同步訪問淮菠,不影響不同對象的同步訪問荤堪,不影響同一對象的非synchronized代碼塊的同步訪問。
  2. 作用在方法
    結(jié)論:跟作用在代碼塊是一樣拥知。
public class ThreadTest implements Runnable{
    private static int count = 0;
    private synchronized void increase() {
            for (int i = 0; i < 3; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + " :" + count++);
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
        }
    }
    @Override
    public void run() {
        increase();
    }
    public static void main(String[] args) {
        //同一個(gè)對象
        ThreadTest threadTest = new ThreadTest();
        Thread t1 = new Thread(threadTest, "t1");
        Thread t2 = new Thread(threadTest, "t2");
        t1.start();
        t2.start();
    }
}

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


image.png

能看出來是互斥同步的,線程2在線程1執(zhí)行結(jié)束肮塞,才開始執(zhí)行。

如果不同的線程作用在不同的對象上:

public static void main(String[] args) {
        //不同線程作用在不同的對象上
        Thread t1 = new Thread(new ThreadTest(), "t1");
        Thread t2 = new Thread(new ThreadTest(), "t2");
        t1.start();
        t2.start();
    }

運(yùn)行結(jié)果:


image.png

能看出來猜欺,線程間是沒有約束的替梨。

然而副瀑,synchronized可以修飾方法恋谭,但它不屬于方法的一部分,因此狈孔,synchronized關(guān)鍵字不能被繼承材义。如果父類方法使用synchronized關(guān)鍵字,而子類中覆蓋了該方法油挥,則子類這個(gè)方法默認(rèn)是不同步的深寥,必須顯式地加上synchronized關(guān)鍵字才會(huì)同步。但是则酝,若在子類中調(diào)用父類相應(yīng)的同步方法闰集,則子類的方法也就相當(dāng)于同步了。

  1. 作用在靜態(tài)方法上
public class ThreadTest implements Runnable{
    private static int count = 0;
    private synchronized static void increase() {
            for (int i = 0; i < 3; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + " :" + count++);
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
        }
    }
    @Override
    public void run() {
        increase();
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(new ThreadTest(), "t1");
        Thread t2 = new Thread(new ThreadTest(), "t2");
        t1.start();
        t2.start();
    }
}

兩個(gè)線程作用在不同的對象上妥泉,運(yùn)行結(jié)果也是互斥同步的。
結(jié)論:跟作用在方法上不同蝇率,synchronized修飾靜態(tài)方法時(shí)本慕,作用范圍是整個(gè)靜態(tài)方法,作用的對象是這個(gè)類的所有對象监氢。這是因?yàn)殪o態(tài)方法是屬于類的而不屬于對象藤违,synchronized的內(nèi)部鎖鎖定這個(gè)類所有對象。

  1. 作用在類上
public class ThreadTest implements Runnable{
    private static int count = 0;
    private void increase() {
        synchronized (ThreadTest.class) {
            for (int i = 0; i < 3; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + " :" + count++);
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    @Override
    public void run() {
        increase();
    }
    public static void main(String[] args) {
        Thread t1 = new Thread(new ThreadTest(), "t1");
        Thread t2 = new Thread(new ThreadTest(), "t2");
        t1.start();
        t2.start();
    }
}

結(jié)論:作用范圍是synchronized后面{}內(nèi)的部分议街,作用的對象也是這個(gè)類的所有對象(跟作用在靜態(tài)方法上一樣)特漩。

tips:

只要明白synchronized關(guān)鍵字是通過對象的內(nèi)部鎖來實(shí)現(xiàn)同步的,再針對具體情況具體分析(靜態(tài)方法涂身、方法搓蚪、類、代碼塊)鳄炉,很快便能搞明白synchronized關(guān)鍵字的含義和用法。

《深入理解java虛擬機(jī)》 周志明
參考文章:https://juejin.im/entry/58070aabd20309006863772c

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拂盯,一起剝皮案震驚了整個(gè)濱河市谈竿,隨后出現(xiàn)的幾起案子摸吠,更是在濱河造成了極大的恐慌,老刑警劉巖呀洲,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件道逗,死亡現(xiàn)場離奇詭異献烦,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)巩那,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門即横,熙熙樓的掌柜王于貴愁眉苦臉地迎上來令境,“玉大人,你說我怎么就攤上這事舔庶。” “怎么了瞧甩?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵肚逸,是天一觀的道長。 經(jīng)常有香客問我膝晾,道長,這世上最難降的妖魔是什么血当? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任臊旭,我火速辦了婚禮箩退,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘戴涝。我一直安慰自己啥刻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蘑拯,像睡著了一般兜粘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上剃法,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天贷洲,我揣著相機(jī)與錄音晋柱,去河邊找鬼。 笑死雁竞,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的彪腔。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼恭垦,長吁一口氣:“原來是場噩夢啊……” “哼盲厌!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起建芙,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤懂扼,失蹤者是張志新(化名)和其女友劉穎阀湿,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體映砖,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡灾挨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年地技,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了秒拔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,779評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡作谚,死狀恐怖食磕,靈堂內(nèi)的尸體忽然破棺而出喳挑,到底是詐尸還是另有隱情滔悉,我是刑警寧澤单绑,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布搂橙,位于F島的核電站区转,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏废离。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一悼尾、第九天 我趴在偏房一處隱蔽的房頂上張望闺魏。 院中可真熱鬧俯画,春花似錦、人聲如沸烹骨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拉宗。三九已至辣辫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間急灭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工卖鲤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人集晚。 一個(gè)月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓区匣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親莲绰。 傳聞我的和親對象是個(gè)殘疾皇子姑丑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評論 2 354

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