如果同时(从多个方面)同时写入java.util.HashMap,会发生什么最糟糕的事情?

时间:2018-06-29 13:15:09

标签: java multithreading hashmap

我有C ++的背景知识,据我所知,对std::map的并发写入访问会产生非常不愉快的后果,在Java中使用java.util.HashMap的情况是什么?

请注意,我想知道在明显的比赛状况之外是否还有不良的副作用。

据我了解,ConcurrentAccessException仅在您从另一个线程修改它的同时循环访问java.util.HashMap时抛出,这意味着简单地调用{{1 }}方法,而另一个线程正在调用get(“安全”是指可能发生的最糟糕的事情是您检索了错误的值)?

是否可能以类似方式导致SEGFAULT?

请注意,“相似”是指仅涉及纯Java方法/对象(没有JNI内容)的竞争条件

3 个答案:

答案 0 :(得分:2)

首先,千万不要那样做,将地图包裹在Collections.synchronizedMap中,这很容易。

内部状态可能会损坏,这可能导致以下任何情况:

[edit]两个新项目(前两个)

  • 由于密钥进入错误的存储桶而导致内存泄漏,除非执行clear(),否则密钥将永远无法被检索/删除
  • 由于哈希表存储桶中的循环循环,导致无限循环
  • 物品遗失(如果未在其他地方使用,则会被垃圾回收)
  • 同一键(迭代时)出现两次的项目
  • 链接到错误键的项目
  • (新)迭代器可能会意外拒绝
  • 如果地图是NavigableMap,则可能会受到额外的推倒

在Java中不会发生诸如段错误之类的硬错误,因为它是一种“安全”语言,在类似情况下会抛出NullPointerException

答案 1 :(得分:2)

可能发生的最坏情况包括:

  • 预期的运行时异常;例如CCME,
  • 意外的运行时异常(NPE的等),
  • 错误的结果;例如get返回错误的值,put丢失条目,或者
  • 无限循环(!)。

我已经看到了所有报告。

原因是,如果在使用共享的HashMap时线程未正确同步,则可能是:

  • 由于公开比赛条件引起的问题,或者
  • 由于一个线程看到各种(允许的)缓存行为而导致陈旧值的问题。
  

是否可能以类似方式导致SEGFAULT?

不。至少,除非您的代码库包含本机代码或使用Unsafe,否则它不会发送JVM错误。

答案 2 :(得分:0)

据我所知,这显然是不安全的,您甚至不应该考虑从不同的线程调用HashMap方法。同样在Java中,您可能不会面对SEGFAULT,就像在C和C ++中可以面对的那样。

相反,您应该考虑使用ConcurrentHashMap