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

时间:2018-09-06 23:38:19

标签: java hashmap concurrentmodification

我有一个静态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);
                }
            }
        }
    }

2 个答案:

答案 0 :(得分:4)

如果多个线程在get上执行putremoveHashMap操作,而没有正确的同步,则size()之类的坏消息会报告条目丢失/丢失,意外的NPE ...甚至可能发生无限循环。

HashMap documentation说-

  

请注意,此实现未同步。如果有多个线程   同时访问哈希映射,并且至少有一个线程   从结构上修改地图,必须在外部进行同步。 (一种   结构修改是添加或删除一个或多个   更多映射;只需更改与   实例已经包含的内容不是结构上的修改。)...

感谢斯蒂芬。

答案 1 :(得分:3)

  

ConcurrentModificationException出发安全吗?

ConcurrentModificationException开始是安全的。该异常仅由使用常规迭代器或分隔器对地图或其视图之一进行迭代(在某种意义上)的方法引发。

但是,由于HashMap不是线程安全的类,因此如果您在没有适当的外部外部同步的情况下从多个线程中使用它,则可能会发生不良情况。这些包括(以增加不良程度为顺序)

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

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