Java并发—锁的四种状态
目錄
無鎖
偏向鎖
輕量級鎖
重量級鎖
總結
鎖的四種狀態:無鎖、偏向鎖、輕量級鎖和重量級鎖
無鎖
無鎖就是沒有真正意義上的上鎖,所有的線程還是能訪問并修改同一個資源,但是通過算法控制,實現同時只有一個線程修改成功。CAS原理及應用即是無鎖的實現。無鎖無法全面代替有鎖,但無鎖在某些場合下的性能是非常高的。比如,CAS全稱 Compare and Swap(比較與交換),是一種無鎖算法。在不使用鎖的情況下(沒有線程被阻塞),實現多線程的變量同步。CAS算法主要涉及到3個操作數:
在最開始將V賦值給A,再進行數據操作生成B,需要更新V之前,比較一下A是否還與V相等,相等說明數據未變化,執行更新操作,不相等,則更新不能完成。
偏向鎖
偏向鎖是指一段同步代碼一直只被一個線程所訪問,那么該線程會自動獲取鎖,降低獲取鎖的成本。例如:家里只有一個碗,但也只有我一個人需要一個碗吃飯,所以不存在爭搶,這就是偏向鎖。因為在大多數情況下,鎖總都是被同一個線程多次反復獲得,不存在多線程競爭,所以就出現了偏向鎖。目標就是在只有一個線程執行同步代碼塊時能夠提高性能。
偏向鎖只有遇到其他線程嘗試競爭偏向鎖時,持有偏向鎖的線程才會釋放鎖,線程不會主動釋放偏向鎖。例如:我家還是只有一個碗,當我朋友來我家和我一起吃飯,這時候就有兩個人,只有這一個碗吃飯,偏向鎖升級。
偏向鎖的撤銷,需要等待全局安全點(在這個時間點上沒有字節碼正在執行),它會首先暫停擁有偏向鎖的線程,判斷鎖對象是否處于被鎖定狀態。撤銷偏向鎖后恢復到輕量級鎖(標志位為“00”)的狀態。 當進入偏向鎖的時候 先進行線程id判斷,如果是同一個線程,那不會進行鎖的升級,如果線程的id不同那么會 進行線程的競爭,這時候會進行鎖升級;
輕量級鎖
是指當鎖是偏向鎖的時候,被另外的線程所訪問,偏向鎖就會升級為輕量級鎖,其他線程會通過自旋的形式嘗試獲取鎖,不會阻塞,從而提高性能。如果這個更新動作成功了,那么這個線程就擁有了該對象的鎖,并且對象Mark Word的鎖標志位設置為“00”,表示此對象處于輕量級鎖定狀態。如果輕量級鎖的更新操作失敗了,虛擬機首先會檢查對象的Mark Word是否指向當前線程的棧幀,如果是就說明當前線程已經擁有了這個對象的鎖,那就可以直接進入同步塊繼續執行,否則說明多個線程競爭鎖。若當前只有一個等待線程,則該線程通過自旋進行等待。但是當自旋超過一定的次數,或者一個線程在持有鎖,一個在自旋,又有第三個來訪時,輕量級鎖升級為重量級鎖。
重量級鎖
當我和女朋友都很餓的時候,我女朋友覺得我吃的太慢了,不想等我吃完,這時候就會去爭搶這唯一的一個碗先吃飯,這是重量級鎖狀態。升級為重量級鎖時,鎖標志的狀態值變為“10”,此時Mark Word中存儲的是指向重量級鎖的指針,此時等待鎖的線程都會進入阻塞狀態。
這里只有如果深入了解 會涉及到 用戶態(輕量級問題)和內核態(重量級問題、操作系統)的問題!!!
總結
整體的鎖狀態升級流程是:無鎖-> 偏向鎖 -> 輕量級鎖 -> 重量級鎖。鎖狀態的改變是根據競爭激烈程度進行的,在幾乎無競爭的條件下,會使用偏向鎖,在輕度競爭的條件下,會由偏向鎖升級為輕量級鎖, 在重度競爭的情況下,會升級到重量級鎖。
- 偏向鎖通過對比Mark Word 解決加鎖問題,避免執行CAS操作。
- 輕量級鎖是通過CAS操作和自旋來解決加鎖問題,避免線程阻塞和喚醒帶來的性能影響。
- 重量級鎖是將除擁有鎖的線程之外的線程全部阻塞。
總結
以上是生活随笔為你收集整理的Java并发—锁的四种状态的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java并发编程—无锁互斥机制及CAS原
- 下一篇: Java 并发编程—核心理论