欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java多線程中synchronized的工作原理

 更新時(shí)間:2023年07月20日 10:23:58   作者:一只愛打拳的程序猿  
這篇文章主要介紹了Java多線程中synchronized的工作原理,本期講解 synchronized 工作的原理以及常見的鎖優(yōu)化機(jī)制,相信大家在看完這篇博文后對 synchronized 工作流程有一定的理解,需要的朋友可以參考下

 1. 鎖的工作流程

眾所周知,synchronized 關(guān)鍵字是用來加鎖的,加鎖的原因就是多個(gè)線程搶占資源導(dǎo)致線程執(zhí)行的過程不具備原子性。

JVM 將 synchronized 加鎖的過程分為四個(gè)狀態(tài)分為無鎖、偏向鎖、輕量級鎖、重量級鎖。

剛開始是無鎖狀態(tài),加上鎖后處于偏向鎖狀態(tài),鎖有了競爭鎖升級為輕量級鎖,鎖的競爭更加激烈了升級為重量級鎖狀態(tài)。

舉例說明:

有個(gè)女孩叫如花,有個(gè)男孩叫阿三,如花是個(gè)漂亮的女孩,阿三是個(gè)帥氣又有錢的男孩。

阿三追求如花,如花不想確定情侶關(guān)系也不想放棄阿三,于是如花吊著阿三,此時(shí)就處于一個(gè)偏向鎖狀態(tài)。阿三就像鎖,鎖的競爭不激烈,如花有恃無恐,鎖處于 偏向鎖 狀態(tài)。

某一天,如花發(fā)現(xiàn)阿三正在被其他女孩追求,如花慌了立馬跟張三確定男女關(guān)系,此時(shí)就處于輕量級鎖狀態(tài)。鎖的競爭激烈了,鎖升級為 輕量級鎖。

隨著日子一天天過去,越來越多女孩開始愛慕阿三。如花更加緊張了,生怕張三離開她,于是越來越限制張三的自由了,此時(shí)就處于重量級鎖狀態(tài)。鎖的競爭更加激烈了,鎖升級為 輕量級鎖。

在上述例子中,阿三為鎖,如花為 JVM。JVM 通過鎖的競爭程度,來決定鎖的策略是什么。

2. 偏向鎖

第一嘗試獲取鎖的線程,優(yōu)先處于偏向鎖的狀態(tài)。此時(shí)這個(gè)線程并未進(jìn)行加鎖操作,而是通過一個(gè) 標(biāo)記 來確定這是第一次獲取鎖的線程。

如果代碼在整個(gè)運(yùn)行過程中,沒有遇到其他線程來競爭鎖。就不會進(jìn)行加鎖了。但,如果有線程進(jìn)行競爭鎖,此時(shí)偏向鎖就會變成一把真正的鎖(輕量級鎖)。

偏向鎖,主要體現(xiàn)能不加鎖就不加鎖這個(gè)概念,它實(shí)際上并沒有加鎖只是通過一個(gè)標(biāo)記來確定鎖于無競爭狀態(tài),等到鎖有競爭情況發(fā)生了,偏向鎖才會變成一把鎖(輕量級鎖)。

舉例:

21世紀(jì)流行著這樣一段關(guān)系:

有一個(gè)男孩小強(qiáng)和一個(gè)女孩小美,小強(qiáng)是一把鎖,小美是一個(gè)線程。小強(qiáng)和小美想過著夫妻一般的生活但不去領(lǐng)證。此時(shí),小美在使用這把鎖的時(shí)候鎖的狀態(tài)為偏向鎖,因?yàn)闆]有其他線程競爭這把鎖。

某一天,小強(qiáng)在公司認(rèn)識了一個(gè)女孩小宣,小宣是一個(gè)線程。小宣愛慕小強(qiáng),于是追求他。小美不想小強(qiáng)被搶走,于是和小強(qiáng)結(jié)婚(領(lǐng)證)。此時(shí),小美使用小強(qiáng)這把鎖就變成了輕量級鎖狀態(tài)。最后小強(qiáng)只得對小宣說:“你是個(gè)好女孩,我配不上你”。

3. 輕量級鎖和重量級鎖

輕量級鎖為了避免進(jìn)入同步狀態(tài),采用了一些基于CAS操作的優(yōu)化手段,但如果線程CAS操作失敗并達(dá)到一定次數(shù)后,會進(jìn)入自旋鎖狀態(tài)等待獲取鎖。但如果自旋等待的時(shí)間過長,就需要升級為重量級鎖,這是為了讓其它線程有機(jī)會搶到鎖。

升級為重量級鎖后,會將當(dāng)前線程阻塞并進(jìn)入內(nèi)核態(tài),而不再直接進(jìn)入自旋鎖狀態(tài)等待,這樣可以避免浪費(fèi)CPU資源。同時(shí),重量級鎖在釋放鎖的時(shí)候,也需要進(jìn)行內(nèi)核態(tài)的操作,因此其釋放鎖的代價(jià)相對較高。

3.1 輕量級鎖

通過上文講解,我們了解到隨著其他線程競爭鎖,鎖由偏向鎖狀態(tài)升級為輕量級鎖狀態(tài)。輕量級鎖狀態(tài),實(shí)際上就是自適應(yīng)的自旋鎖狀態(tài)。

此處的輕量級鎖,是通過 CAS 機(jī)制來實(shí)現(xiàn)的:

通過 CAS 機(jī)制檢查并且更新一塊內(nèi)存。如果更新成功,則加鎖成功。更新失敗,則認(rèn)為鎖被占用,繼續(xù)自旋式的等待。

自旋式,就是通過一個(gè)循環(huán)來判定鎖是否被占用。如果鎖被占用此時(shí)會無限循環(huán),直到鎖不被占用退出循環(huán)。在此期間,自選鎖一直占用著 CPU 資源,比較浪費(fèi)。

3.2 重量級鎖

如果鎖競爭愈發(fā)激烈,自旋鎖不能快速獲取到鎖的狀態(tài),就會升級為重量級鎖。此時(shí)的重量級鎖會引申到內(nèi)核態(tài)與用戶態(tài)。

4. 常見的鎖優(yōu)化

常見的鎖優(yōu)化有兩種:鎖消除于鎖粗化。請看下方講解。

4.1 鎖消除

鎖消除是一種編譯器優(yōu)化機(jī)制,當(dāng)代碼塊被 synchronized 鎖住時(shí)。

如果該代碼塊只被某一線程獨(dú)占則 synchronized 就被編譯器消除了,因?yàn)榫幾g器會檢查并認(rèn)為該代碼塊并不需要加鎖,也就是我們所說的鎖被消除了。

當(dāng)然,多個(gè)線程使用多把鎖時(shí),只要互不干擾各自使用各自的鎖資源,這種情況鎖也會被消除。

鎖消除是一種優(yōu)化技術(shù),它可以減少不必要的鎖操作對性能的影響,提高程序的執(zhí)行效率,節(jié)省系統(tǒng)消耗的資源。

4.2 鎖粗化

談到鎖粗化,我們會聯(lián)想到一個(gè)“粒度感”,代碼越多粒度越粗,代碼越少粒度越細(xì)。在寫代碼的過程中,我們很難兼容到要保證代碼少又要保證代碼好。

比如在某個(gè)場景下,我們頻繁的使用 加鎖/解鎖 操作,編譯器會通過優(yōu)化手段將這些頻繁的 加鎖解鎖 進(jìn)行粗化,這樣就能大大減小系統(tǒng)開銷,也就是我們所說的鎖粗化。

舉例說明:

在公司上班,老板上午安排了一個(gè)任務(wù)給我,下午安排了個(gè)任務(wù)給我,晚上又安排了一個(gè)任務(wù)給我,要求我明天晚上之前要完成。

如果我今天下午完成第一個(gè)任務(wù)打電話給老板并匯報(bào)工作,明天上午完成了第二個(gè)任務(wù)再打電話給老板,明天晚上完成了第三個(gè)任務(wù)又打電話給老板。

老板心里肯定想,這人煩不煩一起給我不就得了。(當(dāng)然,在任務(wù)不緊急的情況下)

如果我一次性匯報(bào)三個(gè)任務(wù),此時(shí)就大大減少了老板接電話(上鎖)掛電話(解鎖)的開銷。

synchronized工作原理是什么?

synchronized 剛開始是無鎖的狀態(tài),當(dāng) synchronized 所修飾的資源被線程獨(dú)占后就升級為偏向鎖狀態(tài),當(dāng) synchronized 被多個(gè)線程競爭后就升級為輕量級鎖,鎖的競爭越來越激烈并且鎖釋放得很慢此時(shí)就會升級為重量級鎖狀態(tài)。

什么是偏向鎖、輕量級鎖、重量級鎖?

  • 偏向鎖:第一個(gè)使用到鎖的線程,此時(shí)并未進(jìn)行鎖操作,編譯器會使用一個(gè)標(biāo)識來確定這個(gè)鎖只被一個(gè)線程使用。
  • 輕量級鎖:當(dāng)鎖被多個(gè)線程競爭了,此時(shí)鎖會從偏向鎖升級為輕量級鎖,輕量級鎖會通過 CAS 機(jī)制即自旋操作,來無限循環(huán)嘗試獲取鎖直到獲取到鎖為止。因此,在獲取到鎖之前會一直占用CPU資源,容易浪費(fèi)資源。
  • 重量級鎖:當(dāng)鎖競爭激烈并且鎖資源釋放過慢,此時(shí)鎖會中輕量級鎖升級為重量級鎖,重量級鎖會跟隨系統(tǒng)的調(diào)度不再進(jìn)行自旋等待,直到鎖釋放了,再參與鎖的競爭,大大減少了系統(tǒng)資源的浪費(fèi)。

到此這篇關(guān)于Java多線程中synchronized的工作原理的文章就介紹到這了,更多相關(guān)synchronized的工作原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java讀取圖片并轉(zhuǎn)化為二進(jìn)制字符串的實(shí)現(xiàn)方法

    java讀取圖片并轉(zhuǎn)化為二進(jìn)制字符串的實(shí)現(xiàn)方法

    這篇文章主要介紹了java讀取圖片并轉(zhuǎn)化為二進(jìn)制字符串的實(shí)例代碼,非常不錯,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-09-09
  • JAVA StringBuffer類與StringTokenizer類代碼解析

    JAVA StringBuffer類與StringTokenizer類代碼解析

    這篇文章主要介紹了JAVA StringBuffer類與StringTokenizer類代碼解析,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • java實(shí)現(xiàn)MD5加密的方法小結(jié)

    java實(shí)現(xiàn)MD5加密的方法小結(jié)

    這篇文章主要介紹了java實(shí)現(xiàn)MD5加密的方法,結(jié)合具體實(shí)例形式總結(jié)分析了java實(shí)現(xiàn)md5加密的常用操作技巧與使用方法,需要的朋友可以參考下
    2017-10-10
  • 實(shí)例講解spring boot 多線程

    實(shí)例講解spring boot 多線程

    這篇文章主要介紹了spring boot 多線程的相關(guān)資料,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • Java雜談之如何消除代碼中一大串參數(shù)列表

    Java雜談之如何消除代碼中一大串參數(shù)列表

    參數(shù)列表和字面意思差不多,主要是表示該參數(shù)數(shù)量不是固定的,可能會有一個(gè)參數(shù),可能多個(gè),不管多少個(gè)參數(shù),都放到一個(gè)數(shù)組處理,這種參數(shù)叫可變參數(shù)。可變長參數(shù)要放在最后一個(gè)參數(shù)位置處理,但是一個(gè)函數(shù)里面不能有倆種類型的可變參數(shù)
    2021-10-10
  • Java中連接數(shù)據(jù)庫方式詳細(xì)步驟記錄

    Java中連接數(shù)據(jù)庫方式詳細(xì)步驟記錄

    這篇文章主要介紹了Java中連接數(shù)據(jù)庫方式的詳細(xì)步驟,包括添加依賴、建立連接、執(zhí)行SQL語句、處理結(jié)果集和關(guān)閉連接,還討論了數(shù)據(jù)庫連接池的使用,需要的朋友可以參考下
    2025-01-01
  • SpringMVC實(shí)現(xiàn)Validation校驗(yàn)過程詳解

    SpringMVC實(shí)現(xiàn)Validation校驗(yàn)過程詳解

    這篇文章主要介紹了SpringMVC實(shí)現(xiàn)Validation校驗(yàn)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • 1秒實(shí)現(xiàn)Springboot 圖片添加水印功能

    1秒實(shí)現(xiàn)Springboot 圖片添加水印功能

    這篇文章主要介紹了1秒實(shí)現(xiàn)Springboot 圖片添加水印功能,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • IntelliJ IDEA本地代碼提交到github網(wǎng)站不顯示與本地不同步問題的解決辦法

    IntelliJ IDEA本地代碼提交到github網(wǎng)站不顯示與本地不同步問題的解決辦法

    今天小編就為大家分享一篇關(guān)于IntelliJ IDEA本地代碼提交到github網(wǎng)站不顯示與本地不同步問題的解決辦法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-10-10
  • Java字符串的壓縮與解壓縮的兩種方法

    Java字符串的壓縮與解壓縮的兩種方法

    這篇文章主要介紹了Java字符串的壓縮與解壓縮的兩種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03

最新評論