![](/img/trans.png)
[英]What is difference between HashMap in synchronized block vs Collections.synchronizedMap().
[英]Difference between Hashtable and Collections.synchronizedMap(HashMap)
據我所知, java.util.Hashtable
同步java.util.Map
接口中的每個方法,而Collections.synchronizedMap(hash_map)
返回一個包裝器對象,其中包含將調用委托給實際hash_map
同步方法(如果我,請更正我)我錯了。
我有兩個問題:
它與同步每個方法和包裝類有什么區別? 有哪些方案可以選擇其中一種?
當我們做Collections.synchronizedMap(hash_table)
時會發生什么? 這是否等於簡單地使用普通的java.util.Hashtable
?
我在兩個類的實現中可以找到的另一個區別如下:
• Hashtable
類的所有方法都已同步,即鎖定是在方法級別完成的,因此可以說互斥鎖始終處於Hashtable
對象( this
)級別。
•方法Collections.synchronizedMap(Map)
返回SynchronizedMap
的實例,它是Collections
類的內部類。 此類在具有互斥鎖的Synchronized
塊中具有其所有方法。 不同之處在於互斥體。 內部類SynchronizedMap
有兩個構造函數,一個只將Map
作為參數,另一個以Map
和Object
(互斥)作為參數。 如果通過使用一個只傳遞一個的第一個構造函數的默認Map
, this
是作為一個互斥。 但是,允許開發人員傳遞另一個互斥對象作為第二個參數,通過該對象, Map
方法上的鎖定僅在該Object
,因此比Hashtable
更少限制。
•因此, Hashtable
使用方法級別同步,但Collections.synchronizedMap(Map)
為開發人員提供了使用Synchronized
塊鎖定所提供的互斥鎖的靈活性。
以下是我從一些(希望是正確的)研究得到的答案:
兩者都提供相同程度的同步。 如果您要通過Collections.synchronized包裝Hashtable
,那么您將具有相同的度數,但具有另一個冗余層,具有同步性。
Hashtable
和Collections.synchronizedMap(HashMap)
之間的主要區別存在於API級別。 由於Hashtable
是Java遺留代碼的一部分,因此您將看到Hashtable
API已得到增強,可實現Map
接口,從而成為Java集合框架的一部分。 這意味着,如果你包Hashtable
通過Collections.synchronizedMap()
包裹的API Hashtable
將成為受限於Map
API。 因此,如果Hashtable
的API包含在您的行為定義中,那么它顯然會被更改/限制。
出現在Java類庫中的第一個關聯集合類是Hashtable,它是JDK 1.0的一部分。 Hashtable提供了一個易於使用,線程安全的關聯映射功能,它當然很方便。 然而,線程安全是有代價的 - 所有Hashtable方法都是同步的。 那時,無競爭同步具有可測量的性能成本。 HashMap的后續版本HashMap作為JDK 1.2中Collections框架的一部分出現,它通過提供一個非同步的基類和一個同步的包裝器Collections.synchronizedMap來解決線程安全問題。 將基本功能與線程安全性Collections.synchronizedMap分離,允許需要同步的用戶擁有它,但不需要它的用戶不必為此付費。
Hashtable和synchronizedMap同步的簡單方法 - 同步Hashtable或同步Map包裝器對象上的每個方法 - 有兩個主要缺陷。 這是可伸縮性的障礙,因為一次只有一個線程可以訪問哈希表。 同時,提供真正的線程安全性是不夠的,因為許多常見的復合操作仍然需要額外的同步。 雖然諸如get()和put()之類的簡單操作可以安全地完成而無需額外的同步,但是有幾種常見的操作序列,例如迭代或put-if-absent,它們仍然需要外部同步以避免數據爭用。
以下鏈接是源代碼,包含更多信息: 並發集合類
差異並非都在明顯的API級別,並且在實現級別存在許多細微之處。 例如, Hashtable
不會使HashMap
高級重新計算提供的密鑰的哈希碼,從而減少哈希沖突。 另一方面, Hashtable#hashCode()
避免了自引用哈希表的無限遞歸,以允許“具有自引用哈希表的某些1.1時代的applet工作”。
但是,一般而言,不應指望Hashtable
接收除基本正確性和向后兼容性之外的任何進一步改進或改進。 它被認為是Java深層歷史遺留下來的遺物。
需要注意的另一個不同點是HashTable不允許空鍵或值,而HashMap允許一個空鍵和任意數量的空值。 由於synchronizedMap是HashMap的包裝器,因此它對null鍵和值的行為與HashMap相同。
陳述明顯(或明顯錯誤)的風險並非如此
同步包裝器將自動同步(線程安全性)添加到任意集合
http://docs.oracle.com/javase/tutorial/collections/implementations/wrapper.html並繼續說
以這種方式創建的集合與正常同步的集合(例如Vector)一樣具有線程安全性。
您可能希望看到此線程有關HashMaps和並發的問題 - Hashmap並發問題 (或者您可能已經非常了解它們)。 一個很好的例子是:
HashMap不會滿足您描述的條件。 由於更新地圖的過程不是原子的,因此您可能會遇到無效狀態的地圖。 多次寫入可能會使其處於損壞狀態。 ConcurrentHashMap(1.5或更高版本)可以滿足您的需求。
https://stackoverflow.com/a/1003071/201648
我想在“我什么時候應該使用它”方面,我傾向於使用需要並發的同步集合,否則你可能會為自己創造更多的工作(見下文)。
在改變行為方面
如果使用顯式迭代器,則必須從synchronized塊中調用迭代器方法。 不遵循此建議可能會導致不確定的行為
在提供的(Oracle)鏈接上使用同步會產生更多后果。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.