我在一本书中读到,在md-button
中读取并不保证最近更新的状态,它有时会给出更接近的值。这是对的吗?
我已阅读其javadocs和许多博客,似乎另有说法(即它是准确的)。
哪一个是真的?
答案 0 :(得分:1)
直观地说,ConcurrentHashMap的行为应该像一组volatile变量;映射键是变量地址。 get(key)
和put(key, value)
应该像易失性读写一样。
文件中没有明确说明。但是,我坚信这是事实。否则会有很多意外的,令人惊讶的行为破坏应用程序逻辑。
我不认为Doug Lea会对我们这样做。当然,有人请在concurrency-interest
邮件列表上问他。
假设它遵循易失性语义,我们可以基于Java内存模型进行推理 -
所有易失性读写形成一个总订单。这可以被认为是伪时间线,其中读/写是其上的点。
易失性读取会看到前一个易失性写入,并且只看到该写入。这里的“前面”是根据伪时间线。
伪时间线可以与“实际”时间线不同。然而,理论上,不能在伪时间线上无限延迟易失性写入。而且,在实践中,两个时间线非常接近。
因此,我们可以非常肯定,一个易变的写入应该“非常快”地显示为读取。
答案 1 :(得分:0)
这就是并发的本质。如果当前挂起的写入操作未安全完成,则任何并发集合都可能在字段中提供旧值。在所有情况下,这都是您所期望的。为并发而创建的集合不会给你损坏的值,如果从多个线程访问它们就会中断,但如果没有写入,它们可能会给你旧的值。
答案 2 :(得分:0)
检索操作(包括get)一般不会阻塞,因此可能与更新操作重叠(包括put和remove)。检索反映了最近完成的更新操作的结果。对于诸如putAll和clear之类的聚合操作,并发检索可能反映仅插入或删除某些条目。类似地,Iterators和Enumerations在迭代器/枚举的创建时或之后的某个时刻返回反映哈希表状态的元素。它们不会抛出ConcurrentModificationException。但是,迭代器被设计为一次只能由一个线程使用。
需要强调的一点是,Iterator
不会反映创建Iterator
后所做的更改。因此,如果您需要迭代地图的值,而其他线程正在添加到地图,并且您关心地图的最新状态,那么使用ConcurrentHashMap
可能不是地图的实现你需要。