溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Sychronized的原理是什么

發(fā)布時(shí)間:2021-06-18 17:58:51 來源:億速云 閱讀:250 作者:Leah 欄目:大數(shù)據(jù)

Sychronized的原理是什么,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

Sychronized原理:

(1)進(jìn)入時(shí):monitorenter

每個(gè)對(duì)象有一個(gè)監(jiān)視器鎖(monitor)。當(dāng)monitor被占用時(shí)就會(huì)處于鎖定狀態(tài),線程執(zhí)行monitorenter指令時(shí)嘗試獲取monitor的所有權(quán),過程如下:
1、如果monitor的進(jìn)入數(shù)為0,則該線程進(jìn)入monitor,然后將進(jìn)入數(shù)設(shè)置為1,該線程即為monitor的所有者。
2、如果該線程已經(jīng)占有該monitor,又重新進(jìn)入,則進(jìn)入monitor的進(jìn)入數(shù)加1。
3、如果其他線程已經(jīng)占用了monitor,則該線程進(jìn)入阻塞狀態(tài),直到monitor的進(jìn)入數(shù)為0,再重新嘗試獲取monitor的所有權(quán)。

(2)退出時(shí):monitorexit

執(zhí)行monitorexit的線程必須是objectref所對(duì)應(yīng)的monitor的所有者。
指令執(zhí)行時(shí),monitor的進(jìn)入數(shù)減1,如果減1后進(jìn)入數(shù)為0,那線程退出monitor,不再是這個(gè)monitor的所有者。其他被這個(gè)monitor阻塞的線程可以嘗試去獲取這個(gè)
monitor 的所有權(quán)。

通過這兩段描述,我們應(yīng)該能很清楚的看出synchronized的實(shí)現(xiàn)原理,synchronized的語義底層是通過一個(gè)monitor的對(duì)象來完成。 
其實(shí)wait/notify等方法也依賴于monitor對(duì)象,這就是為什么只有在同步的塊或者方法中才能調(diào)用wait/notify等方法,否則會(huì)拋出java.lang.IllegalMonitorStateException的異常的原因。

(3)當(dāng)synchronized加在方法前時(shí):

從反編譯的結(jié)果來看,方法的同步并沒有通過指令monitorenter和monitorexit來完成(其實(shí)也可以通過這兩條指令來實(shí)現(xiàn))。

相對(duì)于普通方法,其常量池中多了ACC_SYNCHRONIZED標(biāo)示符。

JVM就是根據(jù)該標(biāo)示符來實(shí)現(xiàn)方法的同步的:

當(dāng)方法被調(diào)用時(shí),調(diào)用指令將會(huì)檢查方法的 ACC_SYNCHRONIZED 訪問標(biāo)志是否被設(shè)置,如果設(shè)置了,執(zhí)行線程將先獲取monitor,獲取成功之后才能執(zhí)行方法體,方法執(zhí)行完后再釋放monitor。在方法執(zhí)行期間,其他任何線程都無法再獲得同一個(gè)monitor對(duì)象。 其實(shí)本質(zhì)上沒有區(qū)別,只是方法的同步是一種隱式的方式來實(shí)現(xiàn),無需通過字節(jié)碼來完成。
--------------------- 
以上轉(zhuǎn)自:https://blog.csdn.net/hbtj_1216/article/details/77773292

JVM對(duì)Sychronized的優(yōu)化:

synchronized中的鎖一般分為重量鎖(對(duì)象鎖),自旋鎖,自適應(yīng)自旋鎖,輕量鎖,偏向鎖

自旋鎖的應(yīng)用場(chǎng)景:

線程的阻塞和喚醒需要CPU從用戶態(tài)轉(zhuǎn)為核心態(tài),頻繁的阻塞和喚醒對(duì)CPU來說是一件負(fù)擔(dān)很重的工作,勢(shì)必會(huì)給系統(tǒng)的并發(fā)性能帶來很大的壓力。同時(shí)我們發(fā)現(xiàn)在許多應(yīng)用上面,對(duì)象鎖的鎖狀態(tài)只會(huì)持續(xù)很短一段時(shí)間,為了這一段很短的時(shí)間頻繁地阻塞和喚醒線程是非常不值得的,所以引入自旋鎖。

若一個(gè)線程等待獲取鎖對(duì)象所持續(xù)的時(shí)間非常短,這時(shí)適合使用自旋鎖。所謂自旋鎖,就是等待鎖的線程并不進(jìn)入阻塞狀態(tài),而是執(zhí)行一個(gè)無意義的循環(huán)。在循環(huán)結(jié)束后查看鎖是否已經(jīng)被釋放,若已經(jīng)釋放則直接進(jìn)入執(zhí)行狀態(tài)。因?yàn)殚L時(shí)間無意義循環(huán)也會(huì)大量浪費(fèi)系統(tǒng)資源,因此自旋鎖適用于間隔時(shí)間短的加鎖場(chǎng)景。

自適應(yīng)自旋鎖對(duì)自旋次數(shù)的調(diào)整:

JDK 1.6引入了更加聰明的自旋鎖,即自適應(yīng)自旋鎖。所謂自適應(yīng)就意味著自旋的次數(shù)不再是固定的,它是由前一次在同一個(gè)鎖上的自旋時(shí)間及鎖的擁有者的狀態(tài)來決定。線程如果自旋成功了,那么下次自旋的次數(shù)會(huì)更加多,因?yàn)樘摂M機(jī)認(rèn)為既然上次成功了,那么此次自旋也很有可能會(huì)再次成功,那么它就會(huì)允許自旋等待持續(xù)的次數(shù)更多。反之,如果對(duì)于某個(gè)鎖,很少有自旋能夠成功的,那么在以后要或者這個(gè)鎖的時(shí)候自旋的次數(shù)會(huì)減少甚至省略掉自旋過程,以免浪費(fèi)處理器資源。

鎖消除

有些情況下,JVM檢測(cè)到不可能存在共享數(shù)據(jù)競(jìng)爭(zhēng),這時(shí)JVM會(huì)對(duì)這些同步鎖進(jìn)行鎖消除。鎖消除的依據(jù)是逃逸分析的數(shù)據(jù)支持。

有時(shí)我們雖然沒有顯示使用鎖,但是我們?cè)谑褂靡恍㎎DK的內(nèi)置API時(shí),如StringBuffer、Vector、HashTable等,它們的內(nèi)部實(shí)現(xiàn)存在隱形的加鎖操作。比如StringBuffer的append()方法,Vector的add()方法。

在運(yùn)行這段代碼時(shí),JVM可以明顯檢測(cè)到變量vector沒有逃逸出方法vectorTest()之外,所以JVM可以大膽地將vector內(nèi)部的加鎖操作消除。

鎖粗化

我們知道在使用同步鎖的時(shí)候,需要讓同步塊的作用范圍盡可能小—僅在共享數(shù)據(jù)的實(shí)際作用域中才進(jìn)行同步,這樣做的目的是為了使需要同步的操作數(shù)量盡可能縮小,如果存在鎖競(jìng)爭(zhēng),那么等待鎖的線程也能盡快拿到鎖。 
在大多數(shù)的情況下,上述觀點(diǎn)是正確的。但是如果一系列的連續(xù)加鎖解鎖操作,可能會(huì)導(dǎo)致不必要的性能損耗,所以引入鎖粗話的概念。 
鎖粗化就是將多個(gè)連續(xù)的加鎖、解鎖操作連接在一起,擴(kuò)展成一個(gè)范圍更大的鎖。如上面實(shí)例:vector每次add的時(shí)候都需要加鎖操作,JVM檢測(cè)到對(duì)同一個(gè)對(duì)象(vector)連續(xù)加鎖、解鎖操作,會(huì)合并一個(gè)更大范圍的加鎖、解鎖操作,即加鎖解鎖操作會(huì)移到for循環(huán)之外。

輕量鎖和偏向鎖

適用于沒有線程競(jìng)爭(zhēng)的情況。無法代替重量鎖

重量級(jí)鎖:

重量級(jí)鎖通過對(duì)象內(nèi)部的監(jiān)視器(monitor)實(shí)現(xiàn),其中monitor的本質(zhì)是依賴于底層操作系統(tǒng)的Mutex Lock實(shí)現(xiàn),操作系統(tǒng)實(shí)現(xiàn)線程之間的切換需要從用戶態(tài)到內(nèi)核態(tài)的切換,切換成本非常高。

(3)上面幾種鎖都是JVM自己內(nèi)部實(shí)現(xiàn),當(dāng)我們執(zhí)行synchronized同步塊的時(shí)候jvm會(huì)根據(jù)啟用的鎖和當(dāng)前線程的爭(zhēng)用情況,決定如何執(zhí)行同步操作;

在所有的鎖都啟用的情況下線程進(jìn)入臨界區(qū)時(shí)會(huì)先去獲取偏向鎖,如果已經(jīng)存在偏向鎖了,則會(huì)嘗試獲取輕量級(jí)鎖,如果以上兩種都失敗,則啟用自旋鎖,如果自旋也沒有獲取到鎖,則使用重量級(jí)鎖,沒有獲取到鎖的線程阻塞掛起,直到持有鎖的線程執(zhí)行完同步塊喚醒他們;

偏向鎖--》輕量級(jí)鎖--》自旋鎖--》重量級(jí)鎖

Sychronized的原理是什么

看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI