Java高效併發(十) JVM中的鎖優化策略

2021-08-21 21:25:59 字數 1798 閱讀 2797

比較交換演算法,cas操作包含三個引數cas(v,e,n),v表示要更新的變數,e表示預期值,n表示新值,當且僅當現在v的值等於e才會把v的值更新為n,如果在v的值不等於e,說明有執行緒對v做了更改,則cas更新失敗,對於更新失敗的執行緒可以繼續嘗試或者放棄更新。

簡單的說就是你給出乙個期望值,如果變數不是你想的期望值,那就說明別人操作過這個值了,你可以重新讀取,更換期望值,然後再嘗試更新就好了。

要清楚除接下來講的偏向鎖和輕量級鎖,首先要說明物件的物件頭,我們知道物件儲存在堆中,包含乙個物件頭部分,markword(32位或者64位),物件頭內容又分為兩部分。一部分是儲存指向方法區中物件型別資料的位址(判斷物件是哪個類的例項),第二部分儲存物件自身的執行時資料,比如hashcode,gc年齡,還有乙個就是鎖標誌位。

偏向鎖,顧名思義偏向第乙個申請鎖的執行緒。對於沒有什麼鎖競爭的場景,偏向鎖將會大大提高效能,因為大多數情況下,連續多次請求同一把鎖是乙個執行緒,適合單執行緒訪問帶同步的資源或方法

第乙個執行緒獲得物件的鎖,jvm就會設定這個物件的物件頭,鎖標誌位是01,然後利用cas操作把指向這個擁有偏向鎖的執行緒id增加到markword中,如果cas更新成功,就進入到偏向模式。當這個執行緒再次請求鎖時,只需要檢查物件頭中的執行緒id還是不是自己,如果是繼續執行,如果不是就檢查物件頭中的鎖標識是否設定成01(表示當前是偏向鎖):如果沒有設定,則使用cas競爭鎖;如果設定了,則嘗試使用cas將物件頭的偏向鎖指向當前執行緒。這個時候如果另外乙個執行緒也在申請鎖jvm會根據這個物件目前的鎖狀態,如果是偏向鎖狀態,jvm會把持有偏向鎖的執行緒會被掛起,jvm會消除它身上的偏向鎖,然後根據物件目前的鎖狀態,更新物件頭鎖標誌,恢復被掛起的執行緒。偏向鎖就失效了。

jvm中通過-xx:+usebiasedlocking引數可以設定是否開啟偏向鎖

加鎖:那麼當乙個執行緒嘗試獲得物件的鎖時,jvm首先會把物件的物件頭資訊拷貝乙份放入到自己的棧幀中,然後通過cas操作讓物件頭的指標指向自己的棧幀,鎖標誌位設定為00,如果這個cas操作成功,這個執行緒就獲得物件的輕量級鎖,如果cas操作失敗,jvm會檢視物件的物件頭的指標,如果指向當前執行緒,這個執行緒就開始執行,如果沒有就說明別的執行緒已經搶占了這個物件的鎖,當前執行緒便嘗試使用自旋來獲取鎖,輕量級鎖在多次cas自旋的過程中沒有獲得鎖,就會自動的公升級成重量級鎖

jvm為了避免真實的將執行緒掛起,還會做最後的努力,就會使用自旋鎖,當申請鎖不得時,讓執行緒原地做空迴圈,等待鎖資源。

可以使用-xx:usespinning來開啟自旋鎖,在jdk1.6之後預設開啟。當然自旋的次數要有限制,預設是10次,也可以使用引數-xx:preblockspin來設定

在jdk1.6中引入了自適應應的自旋鎖,jvm可以根據上一次自旋成功獲得鎖的時間以及鎖的擁有者的狀態來控制自旋時間。

對於一些**上要求同步,但是實際不存在共享資源競爭的鎖,jvm會消除它,鎖消除的判斷依據是逃逸分析技術,也就一段**中堆中的資料不會被其他執行緒訪問到,就可以當做棧上的資料來對待,那麼就是該執行緒私有的,肯定安全,無需加鎖。

比如使用vector容器時,下面**v是區域性變數,執行緒私有而且也沒有發生逃逸,那麼在每次add操作,jvm就會消除vetcor本來操作的synchronized鎖。但是如果下面**返回的是v,那就發生逃逸,jvm就不會執行鎖消除

public string createstring()

return v.toarray(new string{});

}

逃逸分析是需要在-serve模式下進行的,可以使用引數-xx:+eliminatelock引數開啟鎖消除,-xx:+doescapeananlysis開啟逃逸分析。

Java併發編 Java鎖的實現原理

多cpu 一台計算機上多個物理cpu 多核 乙個cpu上多個核心 超執行緒技術 乙個核心多個執行執行單元 高度快取l1 l2 l3 4核8執行緒 這樣就存在快取一致性問題。解決快取一致性問題的方法 匯流排鎖和快取鎖 1 匯流排鎖 這樣之後i的值都為2,但是我們期待的結果是i 3。那麼匯流排鎖的意思是...

JVM中的各種鎖及其優化

自旋鎖 如果兩個或以上的執行緒能夠並行執行,我們可以讓請求鎖的執行緒稍等一下,但不放棄cpu的執行時間,看看持有鎖的執行緒是否很快釋放鎖。為了讓執行緒等待,我們只需讓執行緒執行乙個忙迴圈 自旋 這項技術就是所謂的自旋鎖。虛擬機器在執行時,對於一些 上由同步要求,但被檢測到不可能存在資料共享競爭的鎖進...

併發中的各種鎖

1.執行緒是否要鎖住同步資源 鎖住 悲觀鎖 不鎖住 樂觀鎖 2.鎖住同步資源失敗執行緒是否要阻塞 不阻塞 自旋鎖 適應性自旋鎖 3.synchronized關鍵字優化之後的幾個狀態流 無鎖 偏向鎖 輕量級鎖 重量級鎖 4.多個執行緒競爭鎖時是否排隊 排隊 公平鎖 先嘗試插隊 直接搶鎖 插隊失敗再排隊...