上篇文章:
多線程—鎖策略https://blog.csdn.net/sniper_fandc/article/details/146508232?fromshare=blogdetail&sharetype=blogdetail&sharerId=146508232&sharerefer=PC&sharesource=sniper_fandc&sharefrom=from_link
目錄
1 synchronized的鎖策略
2 synchronized的鎖升級
3 synchronized的鎖消除
4 synchronized的鎖粗化
1 synchronized的鎖策略
????????1.synchronized即是樂觀鎖,也是悲觀鎖(自適應:根據鎖競爭激烈程度升級)。
????????2.synchronized即是輕量級鎖,也是重量級鎖(自適應:根據鎖競爭激烈程度升級)。
????????3.synchronized的輕量級鎖是自旋鎖(基于CAS)實現,重量級鎖是掛起等待鎖(操作系統的mutex鎖實現)。
????????4.synchronized是可重入鎖。
????????5.synchronized不是讀寫鎖,是互斥鎖。
????????6.synchronized是非公平鎖。
2 synchronized的鎖升級
????????1.synchronized一開始采用的是無鎖狀態,即此時沒有任何線程加鎖。
????????2.當有線程嘗試加鎖時,此時synchronized升級為偏向鎖,雖然名字叫鎖,但此時沒有加鎖,只是往鎖對象頭加入了偏向鎖標記,記錄當前鎖是哪個線程的,如果沒有其他線程競爭鎖,就不用真正的加鎖,從而減少了加鎖解鎖的開銷。如果此時有線程競爭鎖,就取消偏向鎖狀態,進入真正的加鎖狀態。
????????3.當偏向鎖進入加鎖狀態時,也就是進入輕量級鎖,基于CAS實現的自旋鎖就是輕量級鎖的實現,此時鎖競爭還不激烈,加鎖操作僅停留在用戶態。(自旋鎖不是一直占有CPU的,而是自旋了一定次數后就會停止嘗試獲取鎖的行為)
????????4.當鎖競爭激烈時,此時自旋鎖無法快速獲得鎖(就會一直浪費CPU資源),那就會升級為重量級鎖。重量級鎖是通過掛起等待鎖實現的,也就是操作系統提供的mutex鎖。當加鎖時會進入內核態,判斷是否能加鎖,如果可以就加鎖并切換回用戶態;否則就把線程掛起等待操作系統的喚醒。
3 synchronized的鎖消除
????????JVM和編譯器底層會判斷當前場景是否是線程安全的,如果是線程安全的環境下用到synchronized,就會進行鎖消除,不再加鎖。比如StringBuffer類是線程安全的,因為其底層的方法中用到synchronized,如果在單線程環境下,就會進行鎖消除。
4 synchronized的鎖粗化
????????鎖分為細粒度(加鎖范圍小)和粗粒度(加鎖范圍大),當頻繁使用細粒度鎖加鎖解鎖時,JVM和編譯器就會把多個細粒度鎖優化成粗粒度鎖,減少頻繁的加鎖解鎖開銷。
下篇文章:
多線程—JUC(java.util.concurrent)https://blog.csdn.net/sniper_fandc/article/details/146713322?fromshare=blogdetail&sharetype=blogdetail&sharerId=146713322&sharerefer=PC&sharesource=sniper_fandc&sharefrom=from_link