Why need synchronizedMap() if there is ConcurrentHashMap?
我读了一篇关于线程安全映射的文章,得到了一个问题。Collections.synchronizedMap()代理基础映射,在每个方法上添加synchronized块。另一方面,ConcurrentHashMap不会在读/写操作中锁定整个映射。这意味着多线程系统中的所有操作都更快。
那么现在使用synchronizedMap()有什么好处呢?我只看到:
它可以从Java 1.2(VS Java 1.5为EDCOX1,2)提供。
可以存储可以为空的值(如果基础映射可以这样做)
有没有其他的情况,当synchronizedMap()更好?
- 如果要同步的地图不是HashMap?
- CHM允许更大的并行性和可扩展性,但是增加的复杂性会消耗额外的内存和性能,因此在低争用环境中可能不值得这样做。另外,synchronizedMap()可以包装各种地图类型,如EnumMap或LinkedHashMap。
与Collections.synchronizedMap(map)和ConcurrentHashMap都有优缺点。
当需要数据一致性时,synchronizedMap非常有用。每个访问线程都将有一个映射的更新视图,这是通过阻塞映射实现的,而阻塞映射又会降低其性能。
当需要经常修改map时,ConcurrentHashMap非常有用。由于它在map的分段/分区上工作,因此多个线程同时在它上工作。但有可能访问线程没有映射的更新视图。另一个优势是它是fail-safe。ConcurrentHashMap不允许空键或值。
使用ConcurrentHashMap,如果性能很重要,则使用数据一致性。
- 这不太对。ConcurrentHashMap分段表。默认值为16,但可以传递更高的值。这意味着您有1/16的机会,您正在访问的条目将被另一个进程锁定。所以你总是有一个最新的地图,但有一个较小的机会,性能罚款,而与synchronizedMap的整个事情被锁定。
- @罗伯特,你所说的ConcurrentHashMap分割是正确的,我不是说ConcurrentHashMap在访问地图时不会给出地图的更新视图。但在高并发环境中,ConcurrentHashMap可能不会返回更新后的地图视图。
- 我想这取决于你如何定义"更新"—读操作不会反映任何挂起的写入操作…但这是尚未完成的写入操作,而不是返回过期值的读取操作。我想你的回答只需要澄清一下就行了。
不是真的。我能想到的另一种情况是很容易使自定义映射实现线程安全。
从Concurrenthashmap文档中:
"...there is not any support for locking the entire table in a way
that prevents all access"
当遍历concurrenthashmap元素时,您可能会看到其他线程同时进行的更新。如果要阻止此类更新,可以改用collections.synchronizedMap()并将迭代逻辑放入synchronized(map)块中。
我可以通过互斥和信号量的异常来翻译这个。
与任何互斥体一样,SynchronizedMap一次只允许一个线程访问支持映射。这确保没有其他线程能够从映射中读/写条目。
对于一个ConcurrentHashMap,就像信号量一样,我们决定一个并发级别,也就是说,一次可以有多少线程去查看您的映射中的条目。
研究何时使用互斥和何时使用信号量可以帮助您进一步消除疑虑。