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

一文帶你徹底剖析Java中Synchronized原理

 更新時間:2023年05月02日 09:59:35   作者:小小小小明明明明明明明明  
Synchronized是Java中的隱式鎖,它的獲取鎖和釋放鎖都是隱式的,完全交由JVM幫助我們操作,在了解Synchronized關(guān)鍵字之前,首先要學習的知識點就是Java的對象結(jié)構(gòu),本文介紹的非常詳細,需要的朋友可以參考下

源碼級別剖析Synchronized

對象結(jié)構(gòu)

Synchronized是Java中的隱式鎖,它的獲取鎖和釋放鎖都是隱式的,完全交由JVM幫助我們操作,在了解Synchronized關(guān)鍵字之前,首先要學習的知識點就是Java的對象結(jié)構(gòu),因為Synchronized鎖就是存放在Java對象中的,Java對象結(jié)構(gòu)如下圖所示:

可以清晰的看到Java對象由三部分組成,分別是對象頭、實例數(shù)據(jù)、填充數(shù)據(jù),我們的鎖就存放在對象頭中,接下來我們將對對象結(jié)構(gòu)做一個簡單的解析:

  • mark-down:對象標記字段占8個字節(jié),用于存儲有關(guān)鎖的標記位等信息,從圖中可以看出有哈希值、輕量級鎖的標記位、偏向鎖標記位等。
  • Klass Pointer:Class對象的類型指針,它就是指向當前對象屬于哪個Class類的指針,jdk1.8默認開啟壓縮指針后占用4個字節(jié),關(guān)閉壓縮指針后占用8個字節(jié)。
  • 對象實際數(shù)據(jù):這部分內(nèi)容包括對象的所有成員變量,大小由各個成員變量決定,比如byte占用1個字節(jié)、int占用4個字節(jié)等。
  • 對其填充:這部分內(nèi)容僅僅只是做到空間補全,就是一個占位符的作用,因為HotSpot虛擬機的內(nèi)存管理系統(tǒng)要求對象的起始地址必須是8字節(jié)的整數(shù)倍,因此如果出現(xiàn)對象實例沒有對齊的話,就需要通過對其填充來補充。

在mark-down鎖類型標記中,可以看到總共有五種類型,分別是無鎖、偏向鎖、輕量級鎖、重量級鎖、GC標記,所以如果只是使用2比特標記是無法完全被表示出來的,所以引入了一位偏向鎖標記,也就是說001為無鎖、101為偏向鎖。

Monitor 對象

上面介紹了對象結(jié)構(gòu),可以看到在Mark-down中會存儲不同的鎖信息,當鎖的狀態(tài)為重量級鎖(10)時,Mark-down中會存放一個指向Monitor對象的指針,這個Monitor對象也稱為監(jiān)視器鎖。

synchronized的運行機制,就是JVM檢測到共享對象存在不同的競爭情況的時候,會自動切換到適合的鎖實現(xiàn),這種切換就是鎖的升級、降級。(很多地方都說鎖只能升級,不能降級,其實這種說法是錯誤的,在《Java并發(fā)編程的藝術(shù)》書中說到,對于偏向鎖來說,它可以進行降級到無鎖狀態(tài),也叫做偏向鎖的撤銷)。

那么現(xiàn)在就存在著三種不同的Monitor實現(xiàn),分別是偏向鎖、輕量級鎖和重量級鎖。如果一個Monitor被一個線程持有的時候,就說明這個線程拿到了鎖。

Java中的Monitor是基于C++的ObjectMonitor實現(xiàn)的,它的主要成員包括:

  • _owner:指向持有ObjectMonitor對象的線程
  • _WaitSet:存放處于wait狀態(tài)的線程隊列,即調(diào)用wait()方法的線程
  • _EntryList:存放處于等待鎖Block狀態(tài)的線程隊列
  • _count:約為_WaitSet+_EntryList的節(jié)點數(shù)之和
  • _cxq:多個線程爭搶鎖,會先存入這個單向鏈表
  • _recursions:記錄重入次數(shù)
  • _object:存儲的Monitor對象

獲取Monitor對象的線程進入_owner區(qū)的時候,_count+1,如果線程調(diào)用了wait()方法,那么會釋放Monitor對象(釋放鎖),_owner恢復為空同時_count-1。此時該線程進入_WaitSet隊列中,等待被喚醒。

從上述的描述可以看出,synchronized關(guān)鍵字獲取鎖的關(guān)鍵在于每個對象的對象頭中,這也就能解釋了為什么synchronized()括號里存放任何對象都能獲得鎖的特征。

Synchronized特征

原子性

原子性,就是說一個操作要么完成,要么不完成,不存在完成一半的情況,也就是說這個操作是不可中斷的。

synchronized可以保證同一時間內(nèi)只有一個線程拿到鎖,進入到代碼塊去執(zhí)行代碼,這樣說如果不能理解,那么就想象下面的一個場景,有一個廁所只有一個坑位,并且?guī)€上鎖了,就是為了防止多人一起上廁所的不文明現(xiàn)象,每個人上廁所都必須要去廁所管理員處繳費,繳費后才能拿到鎖再去上廁所,上完廁所再把要是還給廁所管理員,synchronized就是廁所管理員,保證一次只能有一個人拿到鎖,并且每個人用完廁所之后都必須要歸還鑰匙。

接下來看到下面一個同步加方法:

public static void add() {
    synchronized (Demo.class) {
        counter++;
    }
}

將其進行反編譯后查看代碼:

javap -v -p Demo

public static void add();
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC , ACC_SYNCHRONIZED
    Code:
      stack=2, locals=2, args_size=0
         0: ldc           #12                 // class
         2: dup
         3: astore_0
         4: monitorenter
         5: getstatic     #10                 // Field counter:I
         8: iconst_1
         9: iadd
        10: putstatic     #10                 // Field counter:I
        13: aload_0
        14: monitorexit
        15: goto          23
        18: astore_1
        19: aload_0
        20: monitorexit
        21: aload_1
        22: athrow
        23: return
      Exception table:

可以看到有兩個指令明顯和monitor有關(guān):

  • monitorenter:在判斷擁有同步標識 ACC_SYNCHRONIZED 搶先進入此方法的線程會優(yōu)先擁有 Monitor 的 owner ,此時計數(shù)器 +1
  • monitorexit:當執(zhí)行完退出后,計數(shù)器 -1,歸 0 后被其他進入的線程獲得

可見性

可見性指的是當多個線程訪問同一個變量時,一個線程修改了這個變量的值,其他的線程能夠立馬感知,能看到修改后的值。(線程的可見性和一個叫JMM的東西息息相關(guān),后面會寫一篇關(guān)于可見性結(jié)合volatile關(guān)鍵字的文章)

而Synchronized擁有可見性,因為它加鎖和釋放鎖都有如下語義:

  • 線程加鎖前,必須清空工作內(nèi)存中共享變量的值,從而從主內(nèi)存中讀取最新的共享變量的值。
  • 線程釋放鎖時,必須把共享變量的值刷新到主內(nèi)存中。
  • synchronized的可見性依賴于操作系統(tǒng)內(nèi)核互斥鎖實現(xiàn),相當于JVM中的lock,unlock,退出代碼塊時需要刷新共享變量到主內(nèi)存中,這一點和volatile關(guān)鍵字不一樣,volatile關(guān)鍵字的可見性是依賴于內(nèi)存屏障(也叫內(nèi)存柵欄)來實現(xiàn)的。

有序性

as-if-serial,就是保證不管編譯器和處理器為了性能優(yōu)化怎樣進行指令重排序,都需要保證單線程下的運行結(jié)果的正確性。也就是常說的:如果在本線程內(nèi)觀察,所有的操作都是有序的,如果在一個線程觀察另一個線程,所有的操作都是無序的。

注意,這里的有序性和volatile是不一樣的,它并不是volatile的防止指令重排序。

可重入鎖

可重入鎖的概念很簡單,就是一個線程可以多次獲取自己持有的對象鎖,這種鎖就是可重入鎖,同樣的釋放鎖也就需要釋放相同數(shù)量的鎖。synchronized鎖對象中就有一個計數(shù)器,用于存放獲取鎖的次數(shù),也就是重入次數(shù)。

鎖升級的過程

synchronized 鎖有四種交替升級的狀態(tài):無鎖、偏向鎖、輕量級鎖和重量級,這幾個狀態(tài)隨著競爭情況逐漸升級,后續(xù)會補上一張完整的鎖升級圖

以上就是一文帶你徹底剖析Java中Synchronized原理的詳細內(nèi)容,更多關(guān)于Java Synchronized的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java中BigInteger類的使用方法詳解(全網(wǎng)最新)

    Java中BigInteger類的使用方法詳解(全網(wǎng)最新)

    這篇文章主要介紹了Java中BigInteger類的使用方法詳解,常用最全系列,本章作為筆記使用,內(nèi)容比較全面,但常用的只有:構(gòu)造函數(shù),基本運算以及compareTo(),intValue(),setBit(),testBit()方法,需要的朋友可以參考下
    2023-05-05
  • 深入了解Java File分隔符和Path分隔符的使用

    深入了解Java File分隔符和Path分隔符的使用

    不同的操作系統(tǒng)使用不同的字符作為文件和路徑分隔符。當我們的應用程序需要在多個平臺上運行時,我們需要正確處理這些問題。Java幫助我們選擇一個合適的分隔符,本文就來聊聊Java中File分隔符和 Path分隔符的使用
    2022-07-07
  • Java StringBuffer與StringBuilder有什么區(qū)別

    Java StringBuffer與StringBuilder有什么區(qū)別

    當對字符串進行修改的時候,需要使用 StringBuffer 和 StringBuilder類,和String類不同的是,StringBuffer和 StringBuilder類的對象能夠被多次的修改,并且不產(chǎn)生新的未使用對象,本篇我們來分析分析它們的區(qū)別
    2023-01-01
  • 理解java多線程中ExecutorService使用

    理解java多線程中ExecutorService使用

    這篇文章主要幫助大家理解java多線程中ExcetorServiced的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • Java中的CopyOnWriteArrayList原理詳解

    Java中的CopyOnWriteArrayList原理詳解

    這篇文章主要介紹了Java中的CopyOnWriteArrayList原理詳解,如源碼所示,CopyOnWriteArrayList和ArrayList一樣,都在內(nèi)部維護了一個數(shù)組,操作CopyOnWriteArrayList其實就是在操作內(nèi)部的數(shù)組,需要的朋友可以參考下
    2023-12-12
  • java利用oss實現(xiàn)下載功能

    java利用oss實現(xiàn)下載功能

    這篇文章主要為大家詳細介紹了java利用oss實現(xiàn)下載功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • java讀取簡單excel通用工具類

    java讀取簡單excel通用工具類

    這篇文章主要為大家詳細介紹了java讀取簡單excel通用工具類,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • 詳解Java對象的內(nèi)存布局

    詳解Java對象的內(nèi)存布局

    這篇文章主要介紹了Java對象的內(nèi)存布局,對對象內(nèi)存感興趣的同學,一定要仔細研究下
    2021-04-04
  • 詳解Java如何優(yōu)雅地書寫if-else

    詳解Java如何優(yōu)雅地書寫if-else

    在日常開發(fā)中我們常常遇到有多個if?else的情況,之間書寫顯得代碼冗余難看,對于追求更高質(zhì)量代碼的同學,就會思考如何優(yōu)雅地處理這種代碼。本文我們就來探討下幾種優(yōu)化if?else的方法
    2022-08-08
  • Spring boot 打jar包分離lib的正確配置方式

    Spring boot 打jar包分離lib的正確配置方式

    spring boot打jar包分離lib后,配置文件的方式,在網(wǎng)上可以搜到很多答案,但是都不夠完善,今天小編給大家?guī)砹薙pring boot 打jar包分離lib的正確配置方式,感興趣的朋友一起看看吧
    2018-02-02

最新評論