使用Map和ConcurrentHashMap时的线程安全性

4
以下是两种方法,都创建了concurrentHashMap实例。我的理解是,第二种方法是线程安全的,但第一种方法不是。但是我正在与同事交谈,他认为既然两种方法都创建了concurrentHashMap实例,那么第一种方法也应该是线程安全的,对吗?
方法1:
private static final Map<key, value> map = new ConcurrentHashMap<key, value>();

方案二:

private static final ConcurrentHashMap<key, value> concurrentHashMap = new ConcurrentHashMap<key, value>();

任何关于此事的澄清都将不胜感激。

5
这基本上就像是说“这是我的儿子约翰”和“这是我的孩子约翰”的区别一样。无论你如何称呼约翰,他始终是约翰。这就是基本的多态性,在考虑更加复杂的多线程和线程安全问题之前,您应该确实理解这一点。 - JB Nizet
你也可以使用 Collections.synchronizedMap(map) - Hannes
4个回答

6
你正在创建一个ConcurrentHashMap,因此在线程安全性方面,两种情况是完全相同的。 ConcurrentHashMap实现了Map接口,在示例1中通过此接口进行调用。但这对于被实例化的底层对象并没有影响。

2

显然,这个对象在两种情况下具有相同的运行时类型。

然而,当被视为一个Map时,putIfAbsent和其他ConcurrentMap方法对客户端是隐藏的。这样做是为了防止客户端使用这些方法并强制他们使用传统的putget,这可能是你的同事所担心的问题。


1

这两种解决方案都是线程安全的。你应该更加熟悉Java接口:) 因为两者都是指向同一个映射实现的引用。第一种解决方案通过接口隐藏了这个事实,而第二种没有。

第一种方法甚至更加干净——在处理集合时建议使用API接口而不是类对象。这将有助于对代码进行更改。

我希望我的解释能有所帮助。


0

以下代码仅创建了一个 Map 对象的指针,并将其实例化为 null。

private static final Map<key, value> map;

以下这行代码是对象真正被创建的地方,在两种情况下都是 ConcurrentHashMap 的实例,变量 map 指向它的地址。这才是最重要的,实际的实例。
map = new ConcurrentHashMap<key, value>();

所以两者之间不能有任何区别!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接