ConcurrentHashMap返回一个弱一致的迭代器,为什么我们应该使用它呢?
我正在阅读Java Concurrecny这本书。 在第85页的第5.2.1节中,它讨论了ConcurrentHashMap及其优点。 然而,在一部分中,书籍声称
ConcurrentHashMap返回的迭代器非常一致。 这意味着这个迭代器可以容忍并发修改,遍历构造迭代器时存在的元素,并且可以(但不保证)反映迭代器构造后对集合的修改。
从我理解为什么并发程序中的整个同步点是允许线程以一致的方式访问共享资源,而ConcurrentHashMap并没有真正实现这一点。 那么为什么要使用呢?
关键是在不需要时避免同步。 如果您不介意在某些情况下看到新元素而在其他情况下没有看到它们,那么使用ConcurrentHashMap
的迭代器可能比在迭代时阻止其他线程添加项目或在迭代器处理时获取一致快照要便宜得多创建。
所以,是的,当你需要同步和一致的迭代器时,你需要一个替代方案 – 但是当你不需要时,你可以利用ConcurrentHashMap
提供的更有效的迭代器。
通过契约, ConcurrentHashMap
应该是线程安全的。 但是,它不应该跨线程保持一致 。
迭代ConcurrentHashMap
,迭代器会在您请求它时获取哈希映射的副本(并且此副本以线程安全的方式进行)并迭代该副本。 是的,没有什么可以保证你在迭代该副本时 ,一些地图条目不会被删除。 但是,以这种方式删除的映射条目仍然存在于迭代器中 。
一切都取决于您需要多么强大的一致性。 如果你需要强大的 – 而不是互斥或其他操作子集将提供你需要的。
但是,有时您需要更少的需求,但是例如,您需要说无锁属性,因为您需要保证吞吐量。 另一方面,您可能根本不需要迭代器或对它们有更严格的限制。
因此,如果您需要的是跨线程共享映射ConcurrentHashMap
(比如在影院中预定它的人)将提供您所需要的 – 如果您有许多工作线程可能会更快,因为您避免互斥同步。 另一方面,速度是有代价的 – 迭代器提供的视图没有必要对应于它创建时的收集状态,并且它可能会遗漏一些在字之后创建的元素(通常在多处理器系统中happens-before
关系变得棘手happens-before
)。
编辑 :正如John Wesley王子所指出的那样,我在看到和写作的时候想到了ConcurrentSkipListMap
。 ConcurrentHashMap
。 大多数要点仍然存在,除了关于无锁的部分(以及来自它的所有内容,如保证吞吐量等)。