繁体   English   中英

是否将Map的值更改为原子操作?

[英]Is changing the value of a Map an atomic operation?

我想知道是否需要同步或使用并发类,或者相反,在多线程环境中使用非并发类并且在地图上不进行同步是不是线程安全的,如果对映射的唯一修改正在改变地图。

我问这个的原因是HashMap(以及其他非并发映射文档)有这样的评论:

请注意,此实现不同步。 be synchronized externally. 如果多个线程同时访问哈希映射,并且至少有一个线程在结构上修改了映射,则在外部进行同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。)这通常通过同步自然封装映射的某个对象来完成。 。

这让我相信如果修改不是结构性的(即没有添加或删除)我应该能够更新(非并发)地图sans同步。

我读这个是对的吗? 即将地图中的值更新为原子过程吗?

更新映射值不是原子过程。 但是,每个尝试同时修改映射值的多个不同线程不会因并发错误而导致非常奇怪的异常或错误。 例如,您不会导致其中一个键/值对消失,或者从地图中删除随机元素。

但是,一个线程在更新键/值对时所做的更新不一定对其他线程可见,除非有其他同步进行(例如,如果值是像AtomicIntegers这样的值)。 除此之外,不能保证线程甚至会看到自己的更新,因为它们可能会受到其他线程的破坏。

希望这可以帮助!

当涉及到更新时, HashMapTreeMap等地图的实现不是原子的,也不是线程安全的,但是当你从Java 1.8开始使用ConcurrentHashMap时,你可以实现原子更新操作。

例如,以下方法将添加特定键的值,或者如果该键没有可用的先前值,则设置该值。

ConcurrentMap<String, Integer> map = new ConcurrentHashMap<>();

int addValue(String key, int value) {
    return map.compute(key, (k, v) -> v == null ? value : v + value);
}

将东西放在HashMap中不是原子操作:

public V put(K key, V value) {
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key.hashCode());
    int i = indexFor(hash, table.length);
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }

    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

使用Collections#synchronizedMap包装HashMap可能是值得的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM