您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關Java中synchronized關鍵字如何應用,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
一 synchronized機制
synchronized
關鍵字是JAVA中常用的同步功能,提供了簡單易用的鎖功能。synchronized
有三種用法,分別為:
用在普通方法上,能夠鎖住當前對象。用在靜態方法上,能夠鎖住類用在代碼塊上,鎖住的是synchronized
()里的對象
在JDK6之前,synchronized
使用的是重量級鎖制,在之后synchronized
加入了鎖膨脹機制,顯著提升了synchronized
關鍵字的效率。
基于synchronized
關鍵字,我們來了解下幾種類別的鎖,并且講解synchronized
的鎖膨脹機制。
synchronized
鎖是非公平鎖。并且一個被synchronized
鎖住的對象或類,就是一把鎖。
另外一提,所有鎖都是存儲在Java對象頭里的,Java對象頭里的Mark Word里默認存儲對象的HashCode,分代年齡和鎖標記位。也就是說Mark Word記錄了鎖的狀態
二 鎖膨脹機制與幾類鎖
鎖膨脹是不可逆的
2.1 偏向鎖
synchronized
在JDK1.6以后默認開啟偏向鎖
,synchronized
最初都是偏向鎖
表現:一個線程獲取鎖成功后,會在對象頭里記錄線程ID,以后該線程獲取和釋放鎖都沒有任何花費。(因為該鎖已經被綁定在該線程上了,且在膨脹前不會改變),如果其他線程嘗試獲取這個鎖,偏向鎖
將會膨脹為輕量鎖
。
優點:在只有一個線程使用鎖的時候獲取和退出鎖沒有任何花費
缺點:鎖競爭激烈會很快升級為輕量鎖
,那么維持偏向鎖
的過程就是在浪費計算機資源。(不過因為偏向鎖
本身就很輕量,因此浪費的資源并不多)
小結:只有一個線程使用鎖的情況下,synchronized
使用的鎖為偏向鎖
。如果鎖競爭激烈,可以通過配置JDK禁用偏向鎖
。
2.2 輕量鎖
一把鎖不止一個線程使用,則偏向鎖
膨脹為輕量鎖
表現:線程獲取輕量鎖
時,會直接用CAS
修改對象頭里鎖的記錄,如果修改失敗,代表此時鎖存在多個線程的競爭,輕量鎖
將會膨脹為重量鎖
。
優點:在線程之間使用鎖不存在競爭時,一次CAS
操作就能獲取和退出鎖
缺點:與偏向鎖
類似
小結:只要一把鎖不止一個線程獲取過,偏向鎖
就會膨脹為輕量鎖
。
2.3 重量鎖
一把鎖存在多線程競爭,則輕量鎖
開始自旋,自旋一定次數后仍沒獲取鎖,則膨脹為重量鎖
(存在競爭時,輕量鎖
雖然會先自旋,但是最終往往都會膨脹為重量鎖
)
表現:線程獲取重量鎖
時,如果獲取失敗(即鎖已被其他線程獲取),則使用自適應自旋鎖
,自旋一定次數后仍沒獲取鎖,則進入阻塞隊列等待。
優點:未獲取到的鎖進入阻塞隊列,節約CPU資源。(好吧感覺其實是沒有啥優點)
缺點:重量鎖
是通過對象內部的監視器(monitor)實現,其中monitor的本質是依賴于底層操作系統的Mutex Lock實現,操作系統實現線程之間的切換需要從用戶態到內核態的切換,切換成本非常高。
小結:只要一把鎖存在多線程競爭,輕量鎖
就會膨脹為重量鎖
。
自旋鎖
synchronized
的輕量鎖
,重量鎖
,使用了自適應自旋鎖
進行性能優化
首先介紹自旋鎖
表現:線程獲取鎖失敗后,不會進入阻塞等待,而是再次嘗試去獲取鎖,如此反復,直到獲取到鎖,或者自旋結束那么會阻塞等待。
解決問題:在某些場景下,線程持有鎖的時間非常短。在線程獲取鎖失敗后,如果線程進入阻塞將會帶來線程上下文的切換,上下文切換的時間可能反而高于線程反復嘗試獲取鎖的時間。此時線程原地等待去重復獲取鎖。反而在性能上更有優勢。
缺點:
單核CPU沒有線程并行,反復嘗試會導致進程無法繼續運行。重復嘗試導致了CPU的占用,如果CPU資源緊張的話反而會性能下降如果鎖的競爭時間過長,不僅沒有性能提升,還浪費了大量CPU資源。
優化:使用自適應自旋鎖
。自適應自旋鎖會根據之前的鎖獲取記錄,優化調整自旋時間,避免造成不必要的自旋。
看完上述內容,你們對Java中synchronized關鍵字如何應用有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。