您好,登錄后才能下訂單哦!
ConcurrentHashMap 和 Hashtable 的區別是什么,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
從原理上分析,Hashtable 實現并發安全的原理是通過 synchronized 關鍵字,從源碼角度,以 clear() 方法為例,代碼如下:
public synchronized void clear() { Entry<?,?> tab[] = table; modCount++; for (int index = tab.length; --index >= 0; ) tab[index] = null; count = 0; }
clear() 方法是被 synchronized 關鍵字所修飾的,同理其他的方法例如 put、get、size 等,也同樣是被 synchronized 關鍵字修飾的。之所以 Hashtable 是線程安全的,是因為幾乎每個方法都被 synchronized 關鍵字所修飾了,這也就保證了線程安全。
Collections.SynchronizedMap(new HashMap()) 的原理和 Hashtable 類似,也是利用 synchronized 實現的。
而 ConcurrentHashMap 實現的原理,卻有大大的不同
本質上它實現線程安全的原理是利用了 CAS + synchronized + Node 節點的方式,這和 Hashtable 的完全利用 synchronized 的方式有很大的不同。
因為它們在線程安全的實現方式上的不同,導致它們在性能方面也有很大的不同。當線程數量增加的時候:
Hashtable 的性能會急劇下降,因為每一次修改都需要鎖住整個對象,而其他線程在此期間是不能操作的。不僅如此,還會帶來額外的上下文切換等開銷,所以此時它的吞吐量甚至還不如單線程的情況。
而在 ConcurrentHashMap 中,就算上鎖也僅僅會對一部分上鎖而不是全部都上鎖,所以多線程中的吞吐量通常都會大于單線程的情況,也就是說,在并發效率上,ConcurrentHashMap 比 Hashtable 提高了很多。
Hashtable(包括 HashMap)不允許在迭代期間修改內容,否則會拋出ConcurrentModificationException 異常,其原理是檢測 modCount 變量,迭代器的 next() 方法的代碼如下:
public T next() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); return nextElement(); }
next() 方法中,會首先判斷 modCount 是否等于 expectedModCount。其中 expectedModCount 是在迭代器生成的時候隨之生成的,并且不會改變。
它所代表的含義是當前 Hashtable 被修改的次數,而每一次去調用 Hashtable 的包括 addEntry()、remove()、rehash() 等方法中,都會修改 modCount 的值。這樣一來,如果我們在迭代的過程中,去對整個 Hashtable 的內容做了修改的話,也就同樣會反映到 modCount 中。這樣一來,迭代器在進行 next 的時候,也可以感知到,于是它就會發現 modCount 不等于 expectedModCount,就會拋出 ConcurrentModificationException 異常。
所以對于 Hashtable 而言,它是不允許在迭代期間對內容進行修改的。
相反,ConcurrentHashMap 即便在迭代期間修改內容,也不會拋出ConcurrentModificationException。
如果我們有并發的場景,那么使用 ConcurrentHashMap 是最合適的,Hashtable 已經不再推薦使用。
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。