從字節碼角度分析synchronized實現原理

java識堂 發佈 2020-01-25T16:48:30+00:00

synchronized實現原理Java中每一個對象都可以作為鎖,這是synchronized實現同步的基礎:普通同步方法,鎖是當前實例對象靜態同步方法,鎖是當前類的class對象同步方法塊,鎖是括號裡面的對象當一個線程訪問同步代碼塊時,它首先是需要得到鎖才能執行同步代碼,當退出

synchronized實現原理

Java中每一個對象都可以作為鎖,這是synchronized實現同步的基礎:

  1. 普通同步方法,鎖是當前實例對象
  2. 靜態同步方法,鎖是當前類的class對象
  3. 同步方法塊,鎖是括號裡面的對象

當一個線程訪問同步代碼塊時,它首先是需要得到鎖才能執行同步代碼,當退出或者拋出異常時必須要釋放鎖,

Jconsole:java安裝目錄下有個jdk中找到jconsole

反編譯:

通過javap反編譯class文件:



反編譯後,我們可以看到Java編譯器為我們生成的字節碼。在對於doSth和doSth1的處理上稍有不同。也就是說。JVM對於同步方法和同步代碼塊的處理方式不同。

對於同步方法,JVM採用ACC_SYNCHRONIZED標記符來實現同步。 對於同步代碼塊。JVM採用monitorenter、monitorexit兩個指令來實現同步。

Monitorenter

Monitorexit

從上面可以看出,同步代碼塊是使用monitorenter和monitorexit指令實現的,同步方法(在這看不出來需要看JVM底層實現)依靠的是方法修飾符上的ACC_SYNCHRONIZED實現。

  • 同步代碼塊:monitorenter指令插入到同步代碼塊的開始位置,monitorexit指令插入到同步代碼塊的結束位置,JVM需要保證每一個monitorenter都有一個monitorexit與之相對應。任何對象都有一個monitor與之相關聯,當且一個monitor被持有之後,他將處於鎖定狀態。線程執行到monitorenter指令時,將會嘗試獲取對象所對應的monitor所有權,即嘗試獲取對象的鎖;
  • 同步方法:synchronized方法則會被翻譯成普通的方法調用和返回指令如:invokevirtual、areturn指令,在VM字節碼層面並沒有任何特別的指令來實現被synchronized修飾的方法,而是在Class文件的方法表中將該方法的access_flags欄位中的synchronized標誌位置1,表示該方法是同步方法並使用調用該方法的對象或該方法所屬的Class在JVM的內部對象表示Klass做為鎖對象。

Monitor:

什麼是Monitor?我們可以把它理解為一個同步工具,也可以描述為一種同步機制,它通常被描述為一個對象。 與一切皆對象一樣,所有的Java對象是天生的Monitor,每一個Java對象都有成為Monitor的潛質,因為在Java的設計中 ,每一個Java對象自打娘胎里出來就帶了一把看不見的鎖,它叫做內部鎖或者Monitor鎖。 Monitor 是線程私有的數據結構,每一個線程都有一個可用monitor record列表,同時還有一個全局的可用列表。每一個被鎖住的對象都會和一個monitor關聯(對象頭的MarkWord中的LockWord指向monitor的起始地址),同時monitor中有一個Owner欄位存放擁有該鎖的線程的唯一標識,表示該鎖被這個線程占用。其結構如下:


  • Owner:初始時為NULL表示當前沒有任何線程擁有該monitor record,當線程成功擁有該鎖後保存線程唯一標識,當鎖被釋放時又設置為NULL;
  • EntryQ:關聯一個系統互斥鎖(semaphore),阻塞所有試圖鎖住monitor record失敗的線程。
  • RcThis:表示blocked或waiting在該monitor record上的所有線程的個數。
  • Nest:用來實現重入鎖的計數。
  • HashCode:保存從對象頭拷貝過來的HashCode值(可能還包含GC age)。
  • Candidate:用來避免不必要的阻塞或等待線程喚醒,因為每一次只有一個線程能夠成功擁有鎖,如果每次前一個釋放鎖的線程喚醒所有正在阻塞或等待的線程,會引起不必要的上下文切換(從阻塞到就緒然後因為競爭鎖失敗又被阻塞)從而導致性能嚴重下降。Candidate只有兩種可能的值0表示沒有需要喚醒的線程1表示要喚醒一個繼任線程來競爭鎖。

鎖優化

jdk1.6對鎖的實現引入了大量的優化,如自旋鎖、適應性自旋鎖、鎖消除、鎖粗化、偏向鎖、輕量級鎖等技術來減少鎖操作的開銷。 鎖主要存在四中狀態,依次是:無鎖狀態、偏向鎖狀態、輕量級鎖狀態、重量級鎖狀態,他們會隨著競爭的激烈而逐漸升級。注意鎖可以升級不可降級,這種策略是為了提高獲得鎖和釋放鎖的效率。

原文:https://www.cnblogs.com/grow001/p/12232708.html?utm_source=gold_browser_extension

關鍵字: