我有一个静态hashMap,与多个线程共享。我根本不需要迭代地图,而只是使用get
,put
,remove
。从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);
}
}
}
}
答案 0 :(得分:4)
如果多个线程在get
上执行put
,remove
和HashMap
操作,而没有正确的同步,则size()之类的坏消息会报告条目丢失/丢失,意外的NPE ...甚至可能发生无限循环。
HashMap documentation说-
请注意,此实现未同步。如果有多个线程 同时访问哈希映射,并且至少有一个线程 从结构上修改地图,必须在外部进行同步。 (一种 结构修改是添加或删除一个或多个 更多映射;只需更改与 实例已经包含的内容不是结构上的修改。)...
感谢斯蒂芬。
答案 1 :(得分:3)
从
ConcurrentModificationException
出发安全吗?
从ConcurrentModificationException
开始是安全的。该异常仅由使用常规迭代器或分隔器对地图或其视图之一进行迭代(在某种意义上)的方法引发。
但是,由于HashMap
不是线程安全的类,因此如果您在没有适当的外部外部同步的情况下从多个线程中使用它,则可能会发生不良情况。这些包括(以增加不良程度为顺序)
size()
方法报告错误的值。您的示例代码不安全 ... ...但是您不会遇到“快速失败” ConcurrentModificationException
。相反,您可能会在“随机”时间遇到难以解释的错误,而这些错误很难重现。