可以在没有迭代的情况下在HashMap中获取,放置和删除元素导致ConcurrentModificationException?

问题描述 投票:2回答:2

我有一个静态hashMap,与多个线程共享。我根本没有迭代地图,只是使用getputremove。从ConcurrentModificationException安全吗?

该方法看起来像这样

private static Map<Long, Integer> TRACKER = new HashMap<Long,Integer>();
public static void track(Long tid, boolean b) {
        if (b) {
            if (TRACKER.containsKey(tid)) {
                TRACKER.put(tid, TRACKER.get(tid) + 1);
            } else {
                TRACKER.put(tid, 1);
            }
        } else {
            Integer n = TRACKER.get(tid);
            if (n != null) {
                n = n -1;
                if (n == 0) {
                    TRACKER.remove(tid);
                } else {
                    TRACKER.put(tid, n);
                }
            }
        }
    }
java hashmap concurrentmodification
2个回答
3
投票

ConcurrentModificationException安全吗?

ConcurrentModificationException安全。该异常仅由使用传统迭代器或分裂器迭代(在某种意义上)地图或其视图之一的方法抛出。

但是,由于HashMap不是一个线程安全的类,如果你在没有适当的外部外部同步的情况下从多个线程使用它,就会发生不好的事情。这些包括(按照增加的不良顺序)

  1. 报告错误值的size()方法。
  2. 参赛作品暂时或永久地神秘消失。
  3. 可能的NPE和其他未经检查的异常。
  4. 由于多个线程在哈希链中创建循环的不幸操作序列,可能存在无限循环。

你的示例代码是不安全的...但你不会得到“快速失败”ConcurrentModificationException。相反,您可能会在难以重现的“随机”时间内遇到无法解释的错误。


4
投票

如果多个线程在get上执行putremoveHashMap操作,没有正确的同步,一些不好的事情,比如size()报告丢失/丢失的条目,意外的NPE ......甚至可能发生无限循环。

HashMap documentation说 -

请注意,此实现不同步。如果多个线程同时访问哈希映射,并且至少有一个线程在结构上修改了映射,则必须在外部进行同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。)...

谢谢Stephen。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.