1. 程式人生 > >關於hashmap和hashtable的區別,及如何使hashmap變得執行緒安全?(除了synchronized)---concurrentHashmap

關於hashmap和hashtable的區別,及如何使hashmap變得執行緒安全?(除了synchronized)---concurrentHashmap

我們都知道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 效率相對較高(應用場景:讀取多於寫入);