ConcurrentHashMap中的读操作关于返回值是否可靠?

时间:2015-08-27 14:50:40

标签: java multithreading concurrenthashmap

我在一本书中读到,在md-button中读取并不保证最近更新的状态,它有时会给出更接近的值。这是对的吗?

我已阅读其javadocs和许多博客,似乎另有说法(即它是准确的)。

哪一个是真的?

3 个答案:

答案 0 :(得分:1)

直观地说,ConcurrentHashMap的行为应该像一组volatile变量;映射键是变量地址。 get(key)put(key, value)应该像易失性读写一样。

文件中没有明确说明。但是,我坚信这是事实。否则会有很多意外的,令人惊讶的行为破坏应用程序逻辑。 我不认为Doug Lea会对我们这样做。当然,有人请在concurrency-interest邮件列表上问他。

假设它遵循易失性语义,我们可以基于Java内存模型进行推理 -

所有易失性读写形成一个总订单。这可以被认为是伪时间线,其中读/写是其上的点。

易失性读取会看到前一个易失性写入,并且只看到该写入。这里的“前面”是根据伪时间线。

伪时间线可以与“实际”时间线不同。然而,理论上,不能在伪时间线上无限延迟易失性写入。而且,在实践中,两个时间线非常接近。

因此,我们可以非常肯定,一个易变的写入应该“非常快”地显示为读取。

答案 1 :(得分:0)

这就是并发的本质。如果当前挂起的写入操作未安全完成,则任何并发集合都可能在字段中提供旧值。在所有情况下,这都是您所期望的。为并发而创建的集合不会给你损坏的值,如果从多个线程访问它们就会中断,但如果没有写入,它们可能会给你旧的值。

答案 2 :(得分:0)

来自ConcurrentHashMap javadoc

  

检索操作(包括get)一般不会阻塞,因此可能与更新操作重叠(包括put和remove)。检索反映了最近完成的更新操作的结果。对于诸如putAll和clear之类的聚合操作,并发检索可能反映仅插入或删除某些条目。类似地,Iterators和Enumerations在迭代器/枚举的创建时或之后的某个时刻返回反映哈希表状态的元素。它们不会抛出ConcurrentModificationException。但是,迭代器被设计为一次只能由一个线程使用。

需要强调的一点是,Iterator不会反映创建Iterator后所做的更改。因此,如果您需要迭代地图的值,而其他线程正在添加到地图,并且您关心地图的最新状态,那么使用ConcurrentHashMap可能不是地图的实现你需要。