Java 細粒度鎖續篇
阿新 • • 發佈:2020-12-23
在上篇文章中大概介紹了 Java 中細粒度鎖的幾種實現方式,並且針對每種方式都做了優缺點說明,在使用的時候就需要根據業務需求選擇更合適的一種。上篇文章中的最後一種弱引用鎖的實現方式,我在裡面也說了其實還有更優雅的實現,其實也算不上更優雅,只是看起來更優雅,原理還是一樣的,今天我打算用一篇文章的篇幅來好好說下。
首先,我們來再次回顧一下,這裡為什麼可以利用弱引用的特性拿掉分段鎖呢?分段鎖在這裡主要是為了保證每次在建立和移除鎖時的執行緒安全,而採用了弱引用之後,我們不需要每次建立之後都進行移除,因為當弱引用指向的物件引用被釋放之後 Java 會在下一次的 GC 將這弱引用指向的物件回收掉,在經過 GC 之後,當弱引用指向的物件被回收時,弱引用將會進入建立時指定的佇列,然後我們通過佇列中的值來將這些存放在 Map 中的弱引用移除掉,所以我們才能夠順利的拿掉分段鎖。
### WeakHashMap
你注意看弱引用鎖的程式碼實現,裡面在我們獲取鎖的時候有個手動去清理 Map 中被回收的鎖的過程,如果你看過之前的 [談談 Java 中的各種引用型別](http://mp.weixin.qq.com/s?__biz=MzUxNjgzODM1NQ==&mid=2247484297&idx=1&sn=b8b72975c26b6da1d15beefe21b06ce5&chksm=f9a00535ced78c23c81d9a8e9d973fc7cc1ad32e1eb74492303fdf0a7d0c617a59a5b168cf5c&scene=21#wechat_redirect) 這篇文章的話,你應該知道 Java 提供了一個 WeakHashMap 類,他是使用弱引用作為 key,它在 GC 決定將弱引用所指向的 key 物件回收之後,會將當前儲存的 entry 也自動移除,這個是怎麼實現的呢?
其實原理也是一樣的,利用弱引用指向的物件被回收時,弱引用將會進入建立時指定的佇列這一特性,然後通過輪詢佇列來移除元素。只不過將移除的操作完全包裹在 WeakHashMap 類裡面了,你可以看到裡面所有的 public 的增刪改查方法都直接或間接呼叫了expuntgeStaleEntries() 方法,而 expuntgeStaleEntries 方法中就是在輪詢佇列移除被回收的 key 所對應的元素。
```java
private void expungeStaleEntries() {
for (Object x; (x = queue.poll()) != null; ) {
synchronized (queue) {
@SuppressWarnings("unchecked")