如何理解Java中眼花繚亂的各種并發鎖?( 三 )


7)最后,就是鎖再設計和鎖優化的一些情況先來看分段鎖,它是一種鎖的再次設計,并不是具體的一種鎖 。分段鎖設計目的是將鎖的粒度進一步細化,當操作不需要更新整個數組的時候,就僅僅針對數組中的一項進行加鎖操作 。

如何理解Java中眼花繚亂的各種并發鎖?

文章插圖
在 Java 語言中 CurrentHashMap 底層使用分段鎖Segment , 來支持多線程并發操作 。另外,就是鎖優化,包括鎖消除、鎖粗化 。鎖粗化就是將多個同步塊的數量減少 , 并將單個同步塊的作用范圍擴大,本質上就是將多次上鎖、解鎖的請求合并為一次同步請求 。舉個例子 , 一個循環體中有一個代碼同步塊,每次循環都會執行加鎖解鎖操作 。如代碼所示:
private static final Object LOCK = new Object();for(int i = 0;i < 100; i++) {synchronized(LOCK){// do some magic things}}經過鎖粗化后,就變成下面這個樣子:
synchronized(LOCK){for(int i = 0;i < 100; i++) {// do some magic things} }鎖消除是指虛擬機編譯器在運行時檢測到了共享數據沒有競爭的鎖,從而將這些鎖進行消除 。舉個例子讓大家更好理解,來看這樣一段代碼:
public String test(String s1, String s2){StringBuffer stringBuffer = new StringBuffer();stringBuffer.append(s1);stringBuffer.append(s2);return stringBuffer.toString();}上面代碼中的test() 方法,主要作用是將字符串 s1 和字符串 s2 串聯起來 。test() 方法中的三個變量s1, s2,和StringBuffer都是局部變量,局部變量是存儲在棧上的,而棧又是線程私有的,所以就算有多個線程訪問 test() 方法也是線程安全的 。我們都知道 StringBuffer 是線程安全的類,因為append()方法是同步方法,如源碼所示:
// append 是同步方法 public synchronized StringBuffer append(String str) {toStringCache = null;super.append(str);return this;}但是 test() 方法本來就是線程安全的,為了提升效率,虛擬機自動幫我們消除了這些同步鎖,這個過程就被稱為鎖消除 。
3、總結好了,前面講了這么多 , 相信大家已經理解了各種眼花繚亂的鎖 。最后,我用一張腦圖完整地總結了各種鎖的應用場景 。大家可以在面試前拿出來看看,只要是被問到鎖相關的問題 , 相信你一定能夠吊打面試官了 。
如何理解Java中眼花繚亂的各種并發鎖?

文章插圖
腦圖分享鏈接:https://www.processon.com/view/link/633412ea07912955b20d7938最后,分享幾個關于鎖的高頻面試題,看看大家能不能回答出來
1、ReentrantLock與synchronized 的區別2、synchronized和volatile的區別3、synchronized和lock的區別4、什么是死鎖以及如何避免死鎖問題如果你回答不出來,可以去我的主頁看看,這些面試題在往期的視頻中都有分享過 。
我是被編程耽誤的文藝Tom , 如果我的分享對你有幫助,請動動手指一鍵三連分享給更多的人 。關注我,面試不再難!

推薦閱讀