确保在迭代它时获取`ConcurrentHashMap`的所有值,而其他线程放置元素

问题描述 投票:0回答:1

我有一个ConcurrentHashMap,由8个不同的线程填充put。 8个线程中的一个试图用forEach消费者阅读。我的问题是,ConcurrentHashMap只有5-7个条目。

map.put(myContent);

...

map.forEach(element -> ... do something);

如果我添加一个map.size()它出于某种原因显示所有8个条目

map.put(myContent);
map.size();
...
map.forEach(element -> ... do something);

通过ConcurrentHashMap docs表明,迭代地图并不是真正的线程安全。无法确保获得所有条目:

对于诸如putAll和clear之类的聚合操作,并发检索可能反映仅插入或删除某些条目。类似地,Iterators,Spliterators和Enumerations在迭代器/枚举的创建时或之后的某个时刻返回反映哈希表状态的元素。它们不会抛出ConcurrentModificationException。

在我迭代以获得绝对所有条目之前,是否有可能以某种方式等待或同步?

java concurrency hashmap
1个回答
0
投票

ConcurrentHashMap.size()的文档没有提供关于可见性效果的任何保证,它委托以下方法进行实际计数

final long sumCount() {
    CounterCell[] as = counterCells; CounterCell a;
    long sum = baseCount;
    if (as != null) {
        for (int i = 0; i < as.length; ++i) {
            if ((a = as[i]) != null)
                sum += a.value;
        }
    }
    return sum;
}

大概作为一个副作用,它使你的代码中的所有元素都可见,但这不是你应该依赖的东西(至少除非你理解ConcurrentHashMap的内部工作原理,否则我不这样做)。

ConcurrentHashMap的目的是提供线程安全的插入和检索,但我认为迭代以可靠的方式工作很难或不可能。我不知道任何标准的Maps也可以替代,另一个并发映射ConcurrentSkipListMap也说它的迭代器和分裂器是弱一致的。

© www.soinside.com 2019 - 2024. All rights reserved.