如果有 ConcurrentHashMap,为啥需要 synchronizedMap()? [复制]
Posted
技术标签:
【中文标题】如果有 ConcurrentHashMap,为啥需要 synchronizedMap()? [复制]【英文标题】:Why need synchronizedMap() if there is ConcurrentHashMap? [duplicate]如果有 ConcurrentHashMap,为什么需要 synchronizedMap()? [复制] 【发布时间】:2017-08-24 02:45:33 【问题描述】:我阅读了一篇关于线程安全映射的文章并提出了一个问题。 Collections.synchronizedMap()
代理底层映射,在每个方法上添加 synchronized
块。另一方面,ConcurrentHashMap
不会在读/写操作上锁定整个地图。这意味着多线程系统中的所有操作都更快。
那么现在使用synchronizedMap()
有什么好处呢?我只看到了:
-
它从 java 1.2 开始可用(与 java 1.5 相比
ConcurrentHashMap
)
可以存储可以为空的值(如果底层地图可以做到的话)
还有其他情况synchronizedMap()
更好吗?
【问题讨论】:
如果要同步的地图不是HashMap
?
CHM 允许更高的并行化和可扩展性,但增加的复杂性会消耗额外的内存和性能,因此在低争用环境中可能不值得。此外,synchronizedMap()
可以包装各种地图类型,例如 EnumMap
或 LinkedHashMap
。
【参考方案1】:
Collections.synchronizedMap(map)
和 ConcurrentHashMap
各有利弊。
synchronizedMap
在您需要数据一致性时很有用。每个访问线程都会有一个地图的更新视图,这是通过阻塞地图来实现的,这反过来又会降低其性能。
ConcurrentHashMap
在您需要频繁修改map
时很有用。由于它适用于map
的分段/分区,因此多个线程同时在其上工作。但是有可能访问线程可能没有地图的更新视图。另一个优点是它是fail-safe
。 ConcurrentHashMap
不允许空键或空值。
使用ConcurrentHashMap
如果高度关注性能然后数据一致性。
【讨论】:
这不太对。ConcurrentHashMap
对表格进行分段。默认为 16,但您可以传递更高的值。这意味着您有 1/16 的机会正在访问的条目将被另一个进程锁定。因此,您将始终拥有最新的地图图片,但性能损失的可能性较小,而使用 synchronizedMap
时,整个事情都会被锁定。
@robert,您所说的ConcurrentHashMap
分段是正确的,我并不是说ConcurrentHashMap
在访问地图时不会提供更新的地图视图。但是有可能ConcurrentHashMap
在高并发环境下不会返回更新的地图视图。
我想这取决于你如何定义“更新” - 读取不会反映任何待处理的写入......但它是尚未进行的写入,而不是返回的读取过时的价值。我认为您的答案只需要澄清一下即可。【参考方案2】:
我可以借助互斥量与信号量的类比来翻译它。
就像任何 Mutex 一样,synchronizedMap 一次只允许一个线程访问支持映射。这确保没有其他线程能够从映射中读取/写入条目。
对于 ConcurrentHashMap,就像信号量一样,我们决定一个并发级别,即一次有多少线程可以实际进入并查看 Map 中的条目。
关于何时使用 Mutex 以及何时使用 Semaphore 的研究可以帮助您进一步消除疑虑。
【讨论】:
【参考方案3】:来自 ConcurrentHashMap 文档:
"...不支持以某种方式锁定整个表 阻止所有访问"
在遍历 ConcurrentHashMap 元素时,您可能会看到其他线程同时完成更新。如果您想阻止此类更新,您可以使用 Collections.synchronizedMap() 并将迭代逻辑放在 synchronized(map) 块中。
【讨论】:
【参考方案4】:不是真的。我能想到的唯一另一种情况是轻松地使自定义地图实现线程安全。
【讨论】:
以上是关于如果有 ConcurrentHashMap,为啥需要 synchronizedMap()? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
在 Java 7 ConcurrentHashMap 中,为啥在写的时候需要段锁?为啥我们不能再次使用 Unsafe 来保持非阻塞?
70%的Java程序员不知道为啥 ConcurrentHashMap 读操作不需要加锁?
java8 中concurrenthashmap数据结构和HashMap一样,且线程安全 为啥还要HashMap
Java8 中 ConcurrentHashMap工作原理的要点分析