面試必問-幾種執行緒安全的Map解析

weixin_33670713發表於2017-08-13

​HashMap執行緒安全的嗎?

Java中平時用的最多的Map集合就是HashMap了,它是執行緒不安全的。

看下面兩個場景:

1、當用在方法內的區域性變數時,區域性變數屬於當前執行緒級別的變數,其他執行緒訪問不了,所以這時也不存線上程安全不安全的問題了。

2、當用在單例物件成員變數的時候呢?這時候多個執行緒過來訪問的就是同一個HashMap了,對同個HashMap操作這時候就存線上程安全的問題了。

5954965-ed877ab2cdecffd3

執行緒安全的Map

為了避免出現場景2的執行緒安全的問題,不能使用HashMap作為成員變數,要尋求使用執行緒安全的Map,下面來總結下有哪些執行緒安全的Map呢?

1、HashTable

privateMapmap=newHashtable<>();

來看看HashTable的原始碼

5954965-bb32036bd9b0a8dd
5954965-4a263e76560a0a0f

HashTable的get/put方法都被synchronized關鍵字修飾,說明它們是方法級別阻塞的,它們佔用共享資源鎖,所以導致同時只能一個執行緒操作get或者put,而且get/put操作不能同時執行,所以這種同步的集合效率非常低,一般不建議使用這個集合。

2、SynchronizedMap

privateMapmap= Collections.synchronizedMap(newHashMap());

這種是直接使用工具類裡面的方法建立SynchronizedMap,把傳入進行的HashMap物件進行了包裝同步而已,來看看它的原始碼。

5954965-1ea5c95856355776

這個同步方式實現也比較簡單,看出SynchronizedMap的實現方式是加了個物件鎖,每次對HashMap的操作都要先獲取這個mutex的物件鎖才能進入,所以效能也不會比HashTable好到哪裡去,也不建議使用。

3、ConcurrentHashMap - 推薦

privateMapmap=newConcurrentHashMap<>();

這個也是最推薦使用的執行緒安全的Map,也是實現方式最複雜的一個集合,每個版本的實現方式也不一樣,在jdk8之前是使用分段加鎖的一個方式,分成16個桶,每次只加鎖其中一個桶,而在jdk8又加入了紅黑樹和CAS演算法來實現。

5954965-4e579d999fd711a2

雖然實現起來很複雜,但使用起來也是非常簡單的,在java面試中問的頻率也非常高,最重要的是效能要比上面兩種同步方式要快太多,推薦使用。

5954965-d09bdc1d1da4e086

相關文章