![](/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.