天天看點

9.網際網路大廠高頻面試題-鎖

文章目錄

  • ​​公平和非公平鎖​​
  • ​​是什麼​​
  • ​​兩者差別​​
  • ​​題外話sync與reentrantlock​​
  • ​​可重入鎖和遞歸鎖理論知識​​
  • ​​是什麼​​
  • ​​可重入鎖和遞歸鎖代碼驗證​​
  • ​​自旋鎖理論知識​​
  • ​​自旋鎖代碼驗證-手寫一個自旋鎖​​
  • ​​讀寫鎖理論知識​​
  • ​​讀寫鎖代碼驗證​​
  • ​​CountdownLatch​​
  • ​​枚舉優化countdownlatch​​
  • ​​CyclicBarrier​​
  • ​​semaphore​​

公平和非公平鎖

9.網際網路大廠高頻面試題-鎖
9.網際網路大廠高頻面試題-鎖

是什麼

Reentrantlock的構造方法如下:

9.網際網路大廠高頻面試題-鎖

空構造底層是非公平鎖。相當于Reentrantlock(false)。

可以傳入bool類型的參數,來改變鎖的類型,是公平還是非公平。

9.網際網路大廠高頻面試題-鎖

公平和非公平,指的是排序政策。

9.網際網路大廠高頻面試題-鎖

公平鎖:就是有個隊列,執行講究先來後到。

非公平鎖:就是允許有後來的線程加塞執行。

9.網際網路大廠高頻面試題-鎖

優先級反轉:後來的先執行。

饑餓現象:排在最後的總是得不到執行。

兩者差別

9.網際網路大廠高頻面試題-鎖

題外話sync與reentrantlock

9.網際網路大廠高頻面試題-鎖

可重入鎖和遞歸鎖理論知識

9.網際網路大廠高頻面試題-鎖

reentrantlock:字面意思就是可重入鎖。可重入鎖就是遞歸鎖。

9.網際網路大廠高頻面試題-鎖

是什麼

9.網際網路大廠高頻面試題-鎖

進入家裡門之後,再進廚房是不需要開鎖的,跟這個一個道理。

9.網際網路大廠高頻面試題-鎖

這倆是典型的可重入鎖(非公平)。最大作用是避免死鎖。

9.網際網路大廠高頻面試題-鎖

可重入鎖和遞歸鎖代碼驗證

9.網際網路大廠高頻面試題-鎖
9.網際網路大廠高頻面試題-鎖

測試代碼:

9.網際網路大廠高頻面試題-鎖

結果:

9.網際網路大廠高頻面試題-鎖

現象是同步方法可以進入同步方法。

案例二:證明reentrantlock也是重入鎖。

9.網際網路大廠高頻面試題-鎖

代碼補足:

9.網際網路大廠高頻面試題-鎖

測試代碼+執行結果:

9.網際網路大廠高頻面試題-鎖
9.網際網路大廠高頻面試題-鎖

這個實驗證明,reentrantlock也是重入鎖。

類似的場景還有子類調用父類的,也可以證明。

深化了解:如果加兩個鎖呢?

9.網際網路大廠高頻面試題-鎖

首先,編譯器沒報錯,文法是沒有問題的。

運作,也是沒有問題的。

9.網際網路大廠高頻面試題-鎖

說明隻要你的鎖比對上有lock有unlock,幾把都可以的。

但是如果缺一個unlock,沒有全部配對上,文法是沒問題的。但是執行就不行了,沒有解鎖!

9.網際網路大廠高頻面試題-鎖

此時程式卡死了!是以一定要加鎖幾次,就解鎖幾次!

理論+代碼+總結。學習三闆斧,受教了!

自旋鎖理論知識

之前講過的自旋鎖的相關,atomic類是用的unsafe類+cas思想(自旋)。

9.網際網路大廠高頻面試題-鎖

生活中的case:自旋的反義詞是阻塞。我在打電話,有人來問我問題,他就站我身邊或者看到堵塞去忙自己的事 這兩種選擇。忙一會回來看看,忙一會回來看這種行為,就可以了解為自旋。這是老師的例子,我覺得不好。應該是頻繁重新嘗試獲得鎖,就像你在打電話,然後我不斷的問:打完了嗎?打完了嗎?嘗試着我想做的事情。

自旋鎖代碼驗證-手寫一個自旋鎖

9.網際網路大廠高頻面試題-鎖

對引用類型的原子類引用,啥都不寫,指向的就是null。

9.網際網路大廠高頻面試題-鎖
9.網際網路大廠高頻面試題-鎖

通過cas的思想,實作加鎖與解鎖的方法,當有第一個線程通路的時候,mylock的while判定是false(因為對引用類型的原子類引用,啥都不寫,指向的就是null,是以compareAndSet的結果就是true,取反為false),就沒有進入循環,相當于獲得了鎖,解鎖的邏輯是用完了,把目前線程更新為null,可以被其他線程通路了。如果過程中有其他線程進入通路,就會進入while循環,進而不斷嘗試獲得鎖,而不是做線程切換。

測試代碼:

9.網際網路大廠高頻面試題-鎖

運作效果:

9.網際網路大廠高頻面試題-鎖

BB通過線上程裡自旋,完成多次嘗試獲得鎖,而不是阻塞。可能會消耗性能。

讀寫鎖理論知識

9.網際網路大廠高頻面試題-鎖
9.網際網路大廠高頻面試題-鎖

獨占鎖,也叫寫鎖。共享鎖也叫讀鎖,可以被很多線程并發讀。

鎖的進化曆程:

9.網際網路大廠高頻面試題-鎖

以前的鎖,都是獨占的,是以進化出了讀寫分離的讀寫鎖。

很重要的一點:知識點一定要用代碼證明!

9.網際網路大廠高頻面試題-鎖

讀寫鎖代碼驗證

寫法一:

9.網際網路大廠高頻面試題-鎖

原子性得到了保障,配合volatile,滿足jmm模型的三大特性要求,但是讀取的時候也獨占就效率太低了。

題外話:緩存的三大接口:添加,讀取,清空。

模拟一個不加鎖的場景:

9.網際網路大廠高頻面試題-鎖

對于寫操作,滿足原子+獨占,整個過程必須是一個完整的統一體,中間不許被分割,被打斷。

9.網際網路大廠高頻面試題-鎖

測試代碼:5個線程讀,5個線程寫,先寫入再讀取。執行結果:

9.網際網路大廠高頻面試題-鎖

會發現寫入操作,中間被打斷了很多次。這種情況傳統鎖,可以滿足獨占,但是業務場景需要同讀同寫,這樣傳統的鎖就滿足不了需求了,性能太差了。

加入讀寫鎖:

9.網際網路大廠高頻面試題-鎖
9.網際網路大廠高頻面試題-鎖
9.網際網路大廠高頻面試題-鎖

運作結果:

9.網際網路大廠高頻面試題-鎖

效果對比:

9.網際網路大廠高頻面試題-鎖

CountdownLatch

9.網際網路大廠高頻面試題-鎖
9.網際網路大廠高頻面試題-鎖

作用:火箭發射倒計時

9.網際網路大廠高頻面試題-鎖

api翻譯:countdownlatch在初始化的時候會被賦予一個計數,await方法會阻塞線程,直到這個計數減為0(類似火箭發射,燃料正常,逃逸倉正常,電壓正常…)。

示範原生代碼,遇到這種需要等着前面的子節點操作完了之後再執行操作的場景(類似火箭發射),不做處理:

9.網際網路大廠高頻面試題-鎖

結果是原地爆炸:

9.網際網路大廠高頻面試題-鎖

這種場景的解決方案就是countdownlatch。代碼如下:

9.網際網路大廠高頻面試題-鎖

主線程堵塞,在每個線程裡面減一,當count變成0之後,就釋放鎖,然後繼續往下執行。

運作結果:

9.網際網路大廠高頻面試題-鎖

如果現在有這種需求,有id,有實際的名字,要求按照id,不做if判斷的情況下,輸出實際的名字在列印方法中。

上述需求的解決方案就是:枚舉

枚舉優化countdownlatch

這是一種把枚舉當成資料庫(k-v型)來用,也可以用redis緩存,但是用緩存會增加打開關閉的開銷,也不值當的。這種需要對應的場景,用枚舉是很好的選擇,可以省去很多if判斷。

枚舉類的名字就是資料庫的名字,然後每個枚舉裡面的内容就是一條資料。

設計枚舉類:

9.網際網路大廠高頻面試題-鎖

根據id傳回:

9.網際網路大廠高頻面試題-鎖

業務測試代碼改為:

9.網際網路大廠高頻面試題-鎖

測試結果:

9.網際網路大廠高頻面試題-鎖
9.網際網路大廠高頻面試題-鎖

CyclicBarrier

用法:集齊7個龍珠就能召喚神龍。人到齊了才能開會。

9.網際網路大廠高頻面試題-鎖

代碼案例:

9.網際網路大廠高頻面試題-鎖

先到的被堵塞。

9.網際網路大廠高頻面試題-鎖

semaphore

作用:搶車位,多個資源搶多個資源。

9.網際網路大廠高頻面試題-鎖

代碼示範:6個車三個車位

9.網際網路大廠高頻面試題-鎖

繼續閱讀