ConcurrentHashMap与ConcurrentSkipListMap的澄清

时间:2016-01-22 12:36:40

标签: multithreading dictionary concurrency

我想基于API文档澄清一下ConcurrentHashMap与ConcurrentSkipListMap的内容。

从我的理解ConcurrentHashMap gaurantees线程安全插入多个线程。因此,如果您的地图只能由多个线程同时填充,那么就没有问题。然而,API继续建议它不会锁定检索,所以你可能会在这里得到误导性的结果?

相反,对于ConcurrentSkipListMap,它表示:“插入,删除,更新和访问操作由多个线程安全地并行执行”。所以我假设这没有哈希映射所具有的上述检索问题,但显然这通常会带来性能成本?

在实践中,是否有人发现需要使用ConcurrentSkipListMap,因为这种特殊行为,或者检索通常不会导致过期视图?

3 个答案:

答案 0 :(得分:4)

ConcurrentHashMap

  

检索反映了最近完成的更新的结果   开始时的行动。对于诸如的集合操作   putAll和clear,并发检索可能反映插入或   只删除一些条目。

它使用get(key)的volatile语义。如果Thread1调用put(key1, value1)并且在Thread2调用get(key1)之后,Thread2将不会等待Thread1完成其put,它们彼此不同步并且Thread2 可以获得旧的关联值。但是,如果在Thread2尝试put(key1, value1)之前在Thread1中完成get(key1),则保证Thread2获得此更新(value1)。

ConcurrentSkipListMap已排序并提供

  

containsKey,get的平均log(n)时间成本   放置和删除操作及其变体

ConcurrentSkipListMap不是那么快,但在您需要排序的线程安全地图时非常有用。

答案 1 :(得分:2)

  

然而,API继续表明它没有保护锁定以便检索,因此您可能会在此处获得误导性结果?

有趣的是,ConcurrentSkipListMap也没有,事实上CSLM完全没有阻塞。

在Java 7中,出于所有意图和目的,CHM在执行读取时是非阻塞的。实际上,Java 8更新的CHM实现具有完全无阻塞的读取。

这里的要点是CHM和CSLM具有相似的读取语义,不同之处在于时间复杂度。

答案 2 :(得分:0)

从您的问题来看,您似乎已经得出结论,只有ConcurrentHashMap的插入才是线程安全的。

  

从我的理解ConcurrentHashMap gaurantees线程安全插入多个线程。因此,如果您的地图只能由多个线程同时填充,那么就没有问题。

你是怎么得出这个结论的? ConcurrentHashMap文档的第一行暗示所有操作都是线程安全的:

  

一个哈希表,支持检索的完全并发和可更新的预期并发性。

此外,它意味着get()操作可以维持比put()操作更高的并发性。

简单地说ConcurrentHashMap没有您认为具有的检索问题。在大多数情况下,您应该使用ConcurrentHashMap而不是ConcurrentSkipListMap,因为ConcurrentHashMap的效果通常优于ConcurrentSkipListMap。当您需要具有可预测迭代顺序的CurrentSkipListMap或者您需要ConcurrentMap的工具时,您应该只使用NavigableMap