最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java多線程揭秘之synchronized工作原理

 更新時間:2021年10月18日 09:33:28   作者:春風~十一載  
synchronized算是多線程中非常常用的加鎖方式了,但很多人都不太理解其底層的工作原理。本篇文章博主用盡可能通俗易懂的方式來帶大家去看看synchronized究竟是怎么加鎖的

在學習本篇文章時,如果有不太懂的地方,大家也可以先看看博主上一篇文章,鎖的這部分內容是面試中很常見的問題,多學學對自己是非常有幫助的。同時,朋友們如果有什么問題都可以隨時和我探討,大家一起進步!

一. 特性

這部分內容在上篇文章中的 synchronized充當了哪些鎖部分已經介紹過了哦,沒有看的小伙伴可以去看看synchronized的特性

二. 加鎖過程(鎖升級/鎖膨脹)

在Java中JVM虛擬機將synchronized鎖分為無鎖、偏向鎖、輕量級鎖、重量級鎖狀態(tài)。會根據不同的情況,進行不同的升級操作

在這里插入圖片描述

1. 無鎖狀態(tài)

此狀態(tài)理解起來較為簡單,沒有進行線程任務時最開始的狀態(tài)就是無鎖狀態(tài)。

2. 偏向鎖

  • 偏向鎖類似于一種樂觀鎖,當一個線程在執(zhí)行任務時,偏向鎖會給這個線程設定一個標記(并不是真正地加鎖),如果后續(xù)沒有其他線程來競爭這個鎖,那么這個偏向鎖就不會再進行其他的任何操作了,有效避免了因為加鎖過程而產生的內存開銷問題
  • 若有其他線程也競爭這把鎖,那么此時第一個線程會立馬把鎖拿到(因為之前第一個線程已經有了偏向鎖標記,所以很容易拿到)然后進入輕量級鎖的狀態(tài)

偏向鎖的大體思路是能不加鎖就盡量不加鎖避免內存開銷,只做上標記即可,但如果實在要加鎖,也會因為標記的存在而立馬把鎖拿到(類似于高考填志愿保底心態(tài))

3. 輕量級鎖

當進入輕量級鎖鎖狀態(tài)(自適應自旋鎖)后,是完全在用戶態(tài)上實現的,且是基于CAS來完成的操作,因為這個狀態(tài)不涉及到內核態(tài)和用戶態(tài)的切換,也不涉及到線程的阻塞和調度過程。所以并不會對系統(tǒng)的內存有著過于高的開銷,因此可以保證更高效地獲取到鎖(一個線程釋放鎖后,另一個線程會馬上獲取到鎖)

具體步驟

  • 通過 CAS 檢查并更新一塊內存 (比如 null => 該線程引用)
  • 如果更新成功, 則認為加鎖成功
  • 如果更新失敗, 則認為鎖被占用, 繼續(xù)自旋式的等待(并不放棄 CPU)由于自旋操作可能會一直讓CPU 空轉,比較浪費 CPU 資源,因此此處的自旋不會一直持續(xù)進行,而是達到一定的時間(重試)次數,就不再自旋了,也就是所謂的 “自適應”(根據情況來)

4. 重量級鎖

當鎖的競爭變得非常激烈時,如果再按照之前自旋的方式,那么對于CPU的開銷是非常高的,而且此時自旋還不能快速地獲取到鎖的狀態(tài),那么此時就會變成重量級鎖(掛起等待鎖),對于掛起等待鎖來說,鎖的等待過程是釋放CPU的過程,此時會節(jié)省CPU的開銷,但付出的代價是引入了線程的阻塞和調度的開銷(以CPU資源換取性能)
具體過程
此處的重量級鎖就是用到了內核提供的mutex,要執(zhí)行加鎖操作,首先會進入內核態(tài),在內核態(tài)判定當前的鎖是否已經被占用,若該鎖沒有被占用,則加鎖成功,切換回用戶態(tài);若該鎖被占用,則加鎖失敗,此時線程進入鎖的等待隊列去掛起等待,直到鎖被其他線程釋放后,操作系統(tǒng)才會喚醒掛起等待鎖的這個線程,最后這個線程才會獲取到鎖

5. 總結

  • 鎖升級(鎖膨脹)的過程完全是synchronized內部自適應完成的,即根據不同的情況(即鎖沖突的高或低狀態(tài))來升級或降級成對應的狀態(tài),不需要用戶或者程序員去干預,因此使用起來會比較方便。
  • 注意, synchronized在有些JVM版本上是可以同時實現降級和升級的自適應的,但在有些JVM上只能實現升級的自適應。

三. 鎖優(yōu)化

1. 鎖消除

JVM和編譯器提供了一個很好的功能,能判斷某段代碼是否有加鎖的必要(根據情況選擇是否需要加鎖),以防開發(fā)人員加錯鎖而造成無緣無故開銷很大系統(tǒng)內存的情況。
例子
Java提供了兩個類,StringBuilderStringBuffer,其中,前者不會考慮線程安全問題,而后者中的每個方法都帶有了synchronized以確保線程安全。但我們平常在單線程下,這個加鎖是沒有必要的,會白白浪費很多內存資源,這時候,如果開發(fā)人員不小心在單線程中使用了StringBuffer,那么編譯器和JVM也會對其進行一定的優(yōu)化,去把這個鎖消除。
注意,編譯器的判斷也不是每次完全都是正確的,不會每次都會鎖消除,因此,還是要提醒大家在寫代碼過程中自己還是要盡量避免出現此類錯誤

2. 鎖粗化

介紹鎖粗化之前,首先大家得知道鎖的粗細的含義:

  • 如果synchronized代碼塊中包含的代碼比較多,則認為鎖比較粗
  • 如果synchronized代碼塊中包含的代碼比較少,則認為鎖比較細

那么實際開發(fā)中,到底是鎖粗一點好還是細一點好呢?這個還是根據情況來決定的,雖然當鎖里面的代碼量少時會減少線程之間的鎖沖突概率,但是有的情況下,反而當鎖里面的代碼量較多時,運行效率才會更高:

void func(){
        synchronized (this){
            //任務1
        }
        synchronized (this){
            //任務2
        }
        synchronized (this){
            //任務3
        }
    }

大家先來看一看這段代碼,這段代碼是細鎖的情況(一個鎖中的代碼量較少),那么其執(zhí)行效率怎么樣呢?顯然是不太高的,每次加一次鎖都會進行一定的內存開銷,因此我們很有必要對其進行一定地改進,讓鎖粗化:

void func(){
        synchronized (this){
            //任務1
            //任務2
            //任務3
        }
    }

可以看出來,當鎖粗化的時候,會大大提高代碼的執(zhí)行效率
就好比出門買物品A和物品B,我們通常會盡可能地出一次門,將二者一塊買好再回家,而不是先把物品A買好放到家里再出門買物品B,這樣顯然效率是非常低的,而且還很浪費體力

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

相關文章

  • Spring?RestTemplate遠程調用過程

    Spring?RestTemplate遠程調用過程

    這篇文章主要介紹了Spring?RestTemplate遠程調用過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • 如何兩步解決maven依賴導入失敗的問題

    如何兩步解決maven依賴導入失敗的問題

    這篇文章主要介紹了如何兩步解決maven依賴導入失敗的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • java遍歷途中修改數據及刪除數據的方法總結

    java遍歷途中修改數據及刪除數據的方法總結

    在使用java的集合類遍歷數據的時候,在某些情況下可能需要對某些數據進行刪除,下面這篇文章主要給大家介紹了關于java遍歷途中修改數據及刪除數據的方法總結,需要的朋友可以參考下
    2023-10-10
  • JavaMail實現郵件發(fā)送的方法

    JavaMail實現郵件發(fā)送的方法

    這篇文章主要介紹了JavaMail實現郵件發(fā)送的方法,實例分析了java實現郵件發(fā)送的相關技巧,非常具有實用價值,需要的朋友可以參考下
    2015-04-04
  • Java png圖片修改像素rgba值的操作

    Java png圖片修改像素rgba值的操作

    這篇文章主要介紹了Java png圖片修改像素rgba值的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • java jni調用c函數實例分享(java調用c函數)

    java jni調用c函數實例分享(java調用c函數)

    Java代碼中調用C/C++代碼,當然是使用JNI,JNI是Java native interface的簡寫,可以譯作Java原生接口,下面看實例吧
    2013-12-12
  • JDK完全卸載超詳細步驟

    JDK完全卸載超詳細步驟

    這篇文章主要給大家介紹了關于JDK完全卸載超詳細步驟的相關資料,在安裝JDK之前,最好將原來可能安裝過的JDK卸載掉,以免影響到新JDK的使用,需要的朋友可以參考下
    2023-08-08
  • Oracle+Mybatis的foreach insert批量插入報錯的快速解決辦法

    Oracle+Mybatis的foreach insert批量插入報錯的快速解決辦法

    本文給大家介紹Oracle+Mybatis的foreach insert批量插入報錯的快速解決辦法,非常不錯,具有參考借鑒價值,感興趣的朋友參考下吧
    2016-08-08
  • spring如何使用xml裝配bean

    spring如何使用xml裝配bean

    這篇文章主要介紹了spring如何使用xml裝配bean,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • 關于分布式鎖(Redisson)的原理分析

    關于分布式鎖(Redisson)的原理分析

    這篇文章主要介紹了關于分布式鎖(Redisson)的原理,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08

最新評論

祁连县| 甘孜| 通道| 伊川县| 盐城市| 腾冲县| 定兴县| 将乐县| 漳州市| 紫金县| 宁武县| 东城区| 清原| 维西| 云龙县| 迁安市| 巩留县| 天柱县| 连平县| 玉山县| 新民市| 隆德县| 新邵县| 沽源县| 阿克陶县| 西吉县| 永仁县| 绍兴市| 松原市| 长顺县| 新干县| 海城市| 新田县| 景德镇市| 饶平县| 正镶白旗| 灌云县| 德江县| 射阳县| 古丈县| 甘泉县|