synchronized原理學習筆記

synchronized 是Java併發編程中很是重要的角色,這裏簡單記錄對於其原理的學習html

基礎內容

  • synchronized 具備互斥性,能夠保證只有一個線程能夠訪問同步塊編程

  • synchronized 修飾普通方法,鎖爲當前實例對象安全

  • synchronized 修飾靜態方法,鎖爲當前類的Class對象併發

  • synchronized 修飾同步方法塊,鎖爲代碼塊括號中填寫的對象性能

指令實現

  • 同步代碼塊經過monitorentermonitorexit兩條指令控制同步代碼塊的訪問
  • 同步方法經過設置ACC_SYNCHRONIZED標誌符控制(也能夠經過上述兩條指令來實現)

全部Java對象都會有一個monitor,當monitor被持有後,對象就處於鎖定狀態。當執行到monitorenter指令時,線程會嘗試獲取對象的monitor,而執行monitorexit後會釋放對象的monitor學習

Java SE 1.6爲了下降鎖的獲取、釋放形成的性能損耗,增長了偏向鎖、輕量級鎖。鎖的級別由高到低依次爲無鎖狀態、偏向鎖、輕量級鎖、重量級鎖,鎖能夠升級,但不能夠降級優化

偏向鎖

內容操作系統

鎖由同一線程屢次獲取時,會在對象頭中記錄線程ID,並在以後對同步塊的訪問時,不須要進行CAS操做來加鎖、解鎖。線程

Mark Word狀態3d

Mark Word記錄於對象頭,存儲對象的hashcode或鎖信息

這裏補充無鎖狀態的Mark Word狀態

鎖狀態 hashcode 分代年齡 是否偏向鎖 鎖標誌位
無鎖狀態 對象的hashcode 對象分代年齡 0 01

偏向鎖狀態的Mark Word狀態

鎖狀態 Thread ID epoch 分代年齡 是否偏向鎖 鎖標誌位
偏向鎖 記錄指向的線程id epoch 對象分代年齡 1 01

加鎖與解鎖

biasedlock

輕量級鎖

內容

輕量級鎖是經過自旋實現非阻塞同步,屬於樂觀鎖,能夠膨脹爲重量級鎖

Mark Word狀態

鎖狀態 記錄 鎖標誌位
輕量級鎖 指向棧中鎖記錄的指針 00

加鎖與解鎖

加鎖

lightlock

解鎖

lightunlock

重量級鎖

內容

鎖升級爲重量級鎖後,其餘試圖獲取鎖的線程均會被阻塞,等待持有鎖的線程釋放鎖後,被喚醒的線程會開始競爭獲取鎖。

重量級鎖是一種互斥鎖,其依賴於對象內部的monitor鎖實現,在操做系統層面是經過MutexLock實現的。雖然在阻塞時不須要耗費CPU資源,可是線程從阻塞狀態喚醒須要操做系統完成狀態轉換(用戶態到內核態),耗時較長。

Mark Word狀態

鎖狀態 記錄 鎖標誌位
重量級鎖 指向互斥量(重量級鎖)的指針 10

比較

對比表參考《Java併發編程的藝術》

優勢 缺點 適用場景
偏向鎖 加鎖和解鎖不須要額外的消耗,和執行非同步方法相比僅存在納秒級的差距 若是線程間存在鎖競爭,會帶來額外的鎖撤銷的消耗 適用於只有一個線程訪問同步塊的場景
輕量級鎖 非阻塞同步,提升程序響應速度 自旋消耗CPU資源 追求響應時間,同步方法執行速度較快
重量級鎖 線程阻塞時不須要消耗CPU 線程阻塞,響應時間緩慢 追求吞吐量,同步塊執行時間較長

參考文章

  1. 《Java併發編程的藝術》2.2 synchronized的實現原理與應用
  2. 線程安全(上)--完全搞懂synchronized(從偏向鎖到重量級鎖)
  3. Java併發編程:Synchronized底層優化(偏向鎖、輕量級鎖)

若有問題,還請指出

相關文章
相關標籤/搜索