關於hashmap和hashtable的區別,及如何使hashmap變得執行緒安全?(除了synchronized)---concurrentHashmap
阿新 • • 發佈:2018-11-14
我們都知道hashmap是執行緒不安全的,而效率也比較高,他允許我們存入null鍵及null值;
而 hashtable 是執行緒安全的,其效率比較低,不允許我們存入null鍵和null值;
除了非同步及允許使用null值,hashmap與hashtable基本相同;
那麼為什麼hashtable是執行緒安全的呢?我們可以翻看一下:
例如:put 方法,hashtable中幾乎所有的方法都是被synchronized 修飾的;以保證其安全性;
synchronized 可以修飾靜態方法(鎖物件為本類的位元組碼檔案物件)、修飾普通方法(鎖物件為this,即誰呼叫了它)、修飾某段程式碼(鎖物件為任意物件);
再來說hashmap,它的get put 方法沒有加同步,那麼意味著,如果2個執行緒同時put了兩個相同的key時,這2個key會被放到陣列中的同一位置,(hashmap 中的key是
用陣列來儲存的),就會導致其中一個執行緒put的資料被覆蓋;另外:hashmap併發執行put 操作時會引起死迴圈(其實是發生在陣列擴容時,hashmap 中的node連結串列
形成環形資料結構)。
所以在api中給出了這樣的方法保證hashmap的安全:
Map m = Collections.synchronizedMap(new HashMap(...));
當然還有另外一種方法就是:使用ConcurrentHashmap:這個類遵守與Hashtable
相同的功能規範,即支援Hashtable
的所有功能(注意:它不 允許將 null 用作鍵或值);
除此之外還支援多執行緒對map 的讀操作,在執行寫操作時,CHM只鎖住部分的Map,同時支援16個程序進行寫操作,讀操作不受限制;
原因在於
ConcurrentHashmap引用了鎖分割,將map分割為16部分(預設初始容量為16),由不同的鎖控制;
不過,儘管所有操作都是執行緒安全的,獲取操作不 必鎖定,不支援某種以所有訪問的方式鎖定整個表,CHM不會鎖住整個Map
ConcurrentHashmap 要比
Map m = Collections.synchronizedMap(new HashMap(...)); 方法 和hashtable 效率相對較高(應用場景:讀取多於寫入);