亚洲精品中文免费|亚洲日韩中文字幕制服|久久精品亚洲免费|一本之道久久免费

      
      

            <dl id="hur0q"><div id="hur0q"></div></dl>

                面試官:有了解過Synchronized嗎 說說看

                面試官: 有了解過Synchronized嗎 說說看

                前言

                目前正在出一個(gè)Java多線程專題長期系列教程,從入門到進(jìn)階源碼解讀, 篇幅會(huì)較多, 喜歡的話,給個(gè)關(guān)注 ~ 本篇內(nèi)容純理論一點(diǎn)

                相信很多同學(xué)對(duì)synchronized的使用上不陌生,之前也給大家講解過它的使用。本篇主要帶大家深入了解一下它,大家也可以自己試著總結(jié)一下,這也是面試中常常問到的,單純的回答它的基本使用,是驚艷不到面試官的~

                synchronized 介紹

                從字面意思翻譯過來就是同步的意思,所以它也叫同步鎖,我們通常會(huì)給某個(gè)方法或者某塊代碼加上Synchronized鎖來解決多線程中并發(fā)帶來的問題,它也是最常用,最簡單的一種方法

                在Java中,鎖基本上都是基于對(duì)象而言的,所以又稱為對(duì)象鎖, 一個(gè)類通常只有一個(gè)class對(duì)象和n個(gè)實(shí)例對(duì)象,它們共享class對(duì)象,而我們有時(shí)候會(huì)對(duì)class對(duì)象加鎖,所以又稱為class對(duì)象鎖

                這里大家要注意的是對(duì)象需要是一個(gè)非null的對(duì)象,我們通常也叫做對(duì)象監(jiān)視器(Object Monitor)

                重量級(jí)鎖

                在JDK 1.5之前,它是一個(gè)重量級(jí)鎖,我們通常都會(huì)使用它來保證線程同步。在1.5的時(shí)候還提供了一個(gè)Lock接口來實(shí)現(xiàn)同步鎖的功能,我們只需要顯式的獲取鎖和釋放鎖。

                重在哪

                在1.5的時(shí)候,Synchronized它依賴于操作系統(tǒng)底層的Mutex Lock實(shí)現(xiàn),每次釋放鎖和獲取鎖都會(huì)導(dǎo)致用戶態(tài)和內(nèi)核態(tài)的切換,從而增加系統(tǒng)性能的開銷,當(dāng)出現(xiàn)大并發(fā)的情況下,鎖競爭會(huì)比較激烈,性能顯得非常糟糕,所以稱為重量級(jí)鎖,所以大家往往會(huì)選擇Lock鎖。

                鎖優(yōu)化

                但是Synchronized又是那么的簡單好用,又是官方自帶的,怎么可能放棄呢?所以在1.6之后,引入了大量的鎖優(yōu)化,比如自旋鎖,輕量級(jí)鎖, 偏向鎖等,下面我們逐個(gè)看一下~

                synchronized 實(shí)現(xiàn)原理

                我們了解鎖優(yōu)化之前,我們先看一下它的實(shí)現(xiàn)原理。

                首先我們看下同步塊中,因?yàn)樗顷P(guān)鍵字,我們看不到源碼實(shí)現(xiàn),所以只能反編譯看一下,通過 javap -v **.class

                public static void main(String[] args) { synchronized(Demo.class) { System.out.println(“hello”); } }public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=3, args_size=1 0: ldc #2 // class com/thread/base/Demo 2: dup 3: astore_1 4: monitorenter 5: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream; 8: ldc #4 // String hello 10: invokevirtual #5 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 13: aload_1 14: monitorexit 15: goto 23 18: astore_2 19: aload_1 20: monitorexit 21: aload_2 22: athrow 23: return

                我們重點(diǎn)關(guān)注monitorenter和monitorexit,那么他倆是什么意思呢

                monitorenter,如果當(dāng)前 monitor 的進(jìn)入數(shù)為 0 時(shí),線程就會(huì)進(jìn)入 monitor,并且把進(jìn)入數(shù) + 1,那么該線程就是 monitor 的擁有者 (owner)。如果該線程已經(jīng)是 monitor 的擁有者,又重新進(jìn)入,就會(huì)把進(jìn)入數(shù)再次 + 1。也就是可重入。

                monitorexit,執(zhí)行 monitorexit 的線程必須是 monitor 的擁有者,指令執(zhí)行后,monitor 的進(jìn)入數(shù)減 1,如果減 1 后進(jìn)入數(shù)為 0,則該線程會(huì)退出 monitor。其他被阻塞的線程就可以嘗試去獲取 monitor 的所有權(quán)。指令出現(xiàn)了兩次,第 1 次為同步正常退出釋放鎖;第2次為發(fā)生異步退出釋放鎖;

                我們再來看一下, 修飾實(shí)例方法中的表現(xiàn):

                class Demo { public synchronized void hello() { System.out.println(“hello”); }} public synchronized void hello(); descriptor: ()V flags: ACC_PUBLIC, ACC_SYNCHRONIZED Code: stack=2, locals=1, args_size=1 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3 // String hello 5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return LineNumberTable: line 25: 0 line 26: 8 LocalVariableTable: Start Length Slot Name Signature 0 9 0 this Lcom/thread/base/Demo;}

                我們重點(diǎn)關(guān)注ACC_SYNCHRONIZED,它作用就是一旦執(zhí)行到這個(gè)方法時(shí),就會(huì)先判斷是否有標(biāo)志位,如果有,就會(huì)先嘗試獲取 monitor,獲取成功才能執(zhí)行方法,方法執(zhí)行完成后再釋放 monitor。在方法執(zhí)行期間,其他線程都無法獲取同一個(gè) monitor。歸根結(jié)底還是對(duì) monitor 對(duì)象的爭奪,只是同步方法是一種隱式的方式來實(shí)現(xiàn)。

                synchronized 在 JVM 里的實(shí)現(xiàn)就是基于進(jìn)入和退出 monitor 來實(shí)現(xiàn)的,底層則是通過成對(duì)的 MonitorEnter 和 MonitorExit 指令來實(shí)現(xiàn)

                有了以上的認(rèn)識(shí),下面我們就看看鎖優(yōu)化

                Synchronized中的鎖優(yōu)化

                自適應(yīng)自旋鎖

                自旋鎖,之前我們講FutureTask源碼的時(shí)候,有一個(gè)內(nèi)部方法awaitDone(),給大家有介紹過,就是基于它實(shí)現(xiàn)的,今天再給大家總結(jié)一下。

                它的目的是為了避免阻塞和喚醒的切換,在沒有獲得鎖的時(shí)候就不進(jìn)入阻塞,不斷地循環(huán)檢測鎖是否被釋放。但是,它也有弊端,我們通常來講,一個(gè)線程占用鎖的時(shí)間相對(duì)較短,但是萬一占用很長時(shí)間怎么辦?這樣會(huì)占用大量cpu時(shí)間,這樣會(huì)導(dǎo)致性能變差,所以在1.6引入了自適應(yīng)自旋鎖來滿足這樣的場景。

                那么什么是自適應(yīng)自旋鎖呢 自旋的次數(shù)不是固定的,而是由前一次在同一個(gè)鎖上的自旋時(shí)間及鎖的擁有者的狀態(tài)來決定。如果此次自旋成功了,很有可能下一次也能成功,于是允許自旋的次數(shù)就會(huì)更多,反過來說,如果很少有線程能夠自旋成功,很有可能下一次也是失敗,則自旋次數(shù)就更少。這樣一來,就能夠更好的利用系統(tǒng)資源。

                鎖消除

                鎖消除是一種鎖的優(yōu)化策略,這種優(yōu)化更加徹底,在 JVM 編譯時(shí),通過對(duì)運(yùn)行上下文的掃描,去除不可能存在共享資源競爭的鎖。這種優(yōu)化策略可以消除沒有必要的鎖,去除獲取鎖的時(shí)間。

                鎖粗化

                如果一系列的連續(xù)加鎖解鎖操作,可能會(huì)導(dǎo)致不必要的性能損耗,所以引入鎖粗話的概念。意思是將多個(gè)連續(xù)加鎖、解鎖的操作連接在一起,擴(kuò)展成為一個(gè)范圍更大的鎖, 這個(gè)應(yīng)該很好理解

                偏向鎖

                偏向鎖是JDK 1.6引入的,它解決的場景是什么呢 我們大部分使用鎖都是解決多線程場景下的問題,但有時(shí)候往往一個(gè)線程也會(huì)存在這樣的問題,偏向鎖是在單線程執(zhí)行代碼塊時(shí)使用的機(jī)制。

                鎖的爭奪實(shí)際上是 Monitor 對(duì)象的爭奪,還有每個(gè)對(duì)象都有一個(gè)對(duì)象頭,對(duì)象頭是由 Mark Word 和 Klass pointer 組成的。一旦有線程持有了這個(gè)鎖對(duì)象,標(biāo)志位修改為 1,就進(jìn)入偏向模式,同時(shí)會(huì)把這個(gè)線程的 ID 記錄在對(duì)象的 Mark Word 中,當(dāng)同一個(gè)線程再次進(jìn)入時(shí),就不再進(jìn)行同步操作,大大減少了鎖獲取的時(shí)間,從而提高了性能。

                輕量級(jí)鎖

                我們上邊提到的偏向鎖,在多線程情況下如果偏向鎖失敗就會(huì)升級(jí)為輕量級(jí)鎖, Mark Word 的結(jié)構(gòu)也變?yōu)檩p量級(jí)鎖的結(jié)構(gòu)。

                執(zhí)行同步代碼塊之前,JVM 會(huì)在線程的棧幀中創(chuàng)建一個(gè)鎖記錄(Lock Record),并將 Mark Word 拷貝復(fù)制到鎖記錄中。然后嘗試通過 CAS 操作將 Mark Word 中的鎖記錄的指針,指向創(chuàng)建的 Lock Record。如果成功表示獲取鎖狀態(tài)成功,如果失敗,則進(jìn)入自旋獲取鎖狀態(tài)。

                如果自旋鎖失敗,就會(huì)升級(jí)為重量級(jí)鎖,也就是我們之前講的,會(huì)把線程阻塞,需等待喚醒。

                重量級(jí)鎖

                它又稱為悲觀鎖, 升級(jí)到這種情況下,鎖競爭比較激烈,占用時(shí)間也比較長,為了減少cpu的消耗,會(huì)將線程阻塞,進(jìn)入阻塞隊(duì)列。

                synchronized就是通過鎖升級(jí)策略來適應(yīng)不同的場景,所以現(xiàn)在synchronized被優(yōu)化的很好,也是我們項(xiàng)目中往往都會(huì)使用它的理由。

                結(jié)束語

                本節(jié)的內(nèi)容比較多,大家好好理解,特別是鎖的升級(jí)策略。本節(jié)我們提到了Lock鎖,下一節(jié),帶大家深入學(xué)習(xí)一下Java的Lock ~

                往期內(nèi)容推薦

                • Java多線程專題之線程與進(jìn)程概述
                • Java多線程專題之線程類和接口入門
                • Java多線程專題之進(jìn)階學(xué)習(xí)Thread(含源碼分析)
                • Java多線程專題之Callable、Future與FutureTask(含源碼分析)
                • 面試官: 有了解過線程組和線程優(yōu)先級(jí)嗎
                • 面試官: 說一下線程的生命周期過程
                • 面試官: 說一下線程間的通信
                • 面試官: 說一下Java的共享內(nèi)存模型
                • 面試官: 有了解過指令重排嗎,什么是happens-before
                • 面試官: 有了解過volatile關(guān)鍵字嗎 說說看
                • 我的博客(閱讀體驗(yàn)較佳)
                • 寫給初學(xué)者的Java基礎(chǔ)教程
                • 一文帶你快速學(xué)習(xí)Java集合類
                • 花幾分鐘快速了解一下泛型與枚舉
                • Java注解與反射入門到進(jìn)階
                • JavaIO教程從入門到進(jìn)階

                項(xiàng)目源碼(源碼已更新 歡迎star )

                • java-thread-all
                • 地址: https://github.com/qiuChengleiy/java-thread-all.git

                推薦 SpringBoot & SpringCloud (源碼已更新 歡迎star )

                • springboot-all
                • 地址: https://github.com/qiuChengleiy/springboot-all.git
                • SpringBoot系列教程合集
                • 一起來學(xué)SpringCloud合集
                鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權(quán)歸原作者所有,如有侵權(quán)請聯(lián)系管理員(admin#wlmqw.com)刪除。
                用戶投稿
                上一篇 2022年6月12日 18:15
                下一篇 2022年6月12日 18:15

                相關(guān)推薦

                • 分享4條發(fā)微商朋友圈的方法(微商朋友圈應(yīng)該怎么發(fā))

                  對(duì)于微商朋友來說,朋友圈的重要性不言而喻了。 那么微商的朋友圈到底該怎么發(fā)呢? 為什么同樣是經(jīng)營一個(gè)朋友圈,有的微商看起來逼格滿滿,實(shí)際效果也不錯(cuò);而有的卻動(dòng)都不動(dòng)就被屏蔽甚至拉黑…

                  2022年11月27日
                • 《寶可夢朱紫》夢特性怎么獲得?隱藏特性獲取方法推薦

                  寶可夢朱紫里有很多寶可夢都是擁有夢特性會(huì)變強(qiáng)的寶可夢,很多玩家不知道夢特性怎么獲得,下面就給大家?guī)韺毧蓧糁熳想[藏特性獲取方法推薦,感興趣的小伙伴一起來看看吧,希望能幫助到大家。 …

                  2022年11月25日
                • 《寶可夢朱紫》奇魯莉安怎么進(jìn)化?奇魯莉安進(jìn)化方法分享

                  寶可夢朱紫中的奇魯莉安要怎么進(jìn)化呢?很多玩家都不知道,下面就給大家?guī)韺毧蓧糁熳掀骠斃虬策M(jìn)化方法分享,感興趣的小伙伴一起來看看吧,希望能幫助到大家。 奇魯莉安進(jìn)化方法分享 奇魯莉安…

                  2022年11月25日
                • 非匿名指令新手十連怎么選?非匿名指令新手無限十連選擇推薦

                  非匿名指令新手十連怎么選?進(jìn)入游戲之后大家能得到一個(gè)新手無限十連,可以幫大家抽到滿意的角色,新手十連的選擇小編在下面也會(huì)有分享,不知道如何選擇的可以看看小編提供的攻略,了解新手十連…

                  2022年11月25日
                • 5+3疫情防控從哪天開始算(遼寧疫情防控最新政策)

                  最近有關(guān)國內(nèi)各地的疫情大家也都有在持續(xù)關(guān)注,目前國內(nèi)各地疫情隔離時(shí)間也根據(jù)二十條防控措施有了新的調(diào)整。那么,5+3疫情防控從哪天開始算?對(duì)于密接的5+3隔離時(shí)間計(jì)算大家還是比較關(guān)心…

                  2022年11月25日
                • 2023年擺地?cái)傎u什么最賺錢而且很受歡迎(2022年擺地?cái)偤戏▎?

                  關(guān)于擺地?cái)傎嶅X每年的熱度也是非常高的,很多想要做點(diǎn)小本生意的商家也都會(huì)選擇擺地?cái)傔@個(gè)項(xiàng)目,所需要的成本也是非常低的。那么,2023年擺地?cái)傎u什么最賺錢而且很受歡迎?今天極客號(hào)小編整…

                  2022年11月25日
                • 藍(lán)碼怎么變綠碼需要幾天(藍(lán)碼怎么變綠碼需要幾天)

                  大家都知道健康碼的顏色有紅碼、綠碼、黃碼,近日湖南健康碼上線“藍(lán)碼”,不少小伙伴發(fā)現(xiàn)自己健康碼變藍(lán)了,都想趕緊恢復(fù)綠碼,那么藍(lán)碼怎么變綠碼需要幾天?下面小編為大家?guī)硭{(lán)碼變綠碼需要…

                  2022年11月25日
                • 拼多多百億補(bǔ)貼預(yù)售一般多久發(fā)貨(拼多多百億補(bǔ)貼預(yù)售)

                  拼多多里面有很多優(yōu)惠活動(dòng),其中百億補(bǔ)貼活動(dòng)非?;鸨?,一些里面的東西價(jià)格比別的平臺(tái)便宜,質(zhì)量也有保障,還有預(yù)售的活動(dòng),那么拼多多百億補(bǔ)貼預(yù)售一般多久發(fā)貨?下面小編為大家?guī)砥炊喽喟賰|…

                  2022年11月25日
                • 密接5+3是什么意思(密接人員是什么意思)

                  如今新冠病例的傳播速度是越來越快了,對(duì)于感染了新冠病毒的人員來說都會(huì)采取隔離觀看措施。而據(jù)了解,當(dāng)前國內(nèi)又對(duì)新冠疫情防控政策做了新的調(diào)整優(yōu)化,其中密接管理調(diào)整為“5+3”。很多人對(duì)…

                  2022年11月25日
                • 北京疫情多久能解除封控(北京疫情還要多久結(jié)束)

                  最近一段時(shí)間北京疫情形勢備受關(guān)注,馬上就要到年底了,不少人想要去北京辦事,。都非常關(guān)注當(dāng)?shù)匾咔橄嚓P(guān)政策,那么 北京疫情多久能解除封控?北京疫情什么時(shí)候恢復(fù)正常生活?下面小編為大家?guī)А?/p>

                  2022年11月25日

                聯(lián)系我們

                聯(lián)系郵箱:admin#wlmqw.com
                工作時(shí)間:周一至周五,10:30-18:30,節(jié)假日休息