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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如果我同时(从多个线程)写入java.util.HashMap会发生什么最糟糕的事情?相关的知识,希望对你有一定的参考价值。

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

请注意,我想知道在明显的竞争条件旁边是否有不良副作用。

据我所知,ConcurrentAccessException只有在你从另一个线程修改它时才会抛出java.util.HashMap,这是否意味着只需调用get方法而另一个线程调用put(带有“安全”I)是安全的意味着可能发生的最糟糕的事情是你检索错误的值)?

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

请注意,“类似”我的意思是通过竞争条件只涉及纯Java方法/对象(没有JNI的东西)

答案

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

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

[编辑]两个新项目(前两个)

  • 内存泄漏,因为密钥进入错误的桶,除非执行clear(),否则永远无法检索/删除
  • 无限循环,因为散列表桶中的循环循环
  • 丢失的物品(如果不在其他地方使用,它们将被垃圾收集)
  • 对同一个键出现两次的项目(迭代时)
  • 链接到错误密钥的项目
  • (新)迭代器可能意外地进行了调整
  • 如果地图是NavigableMap,您可能会遇到额外的呕吐

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

另一答案

可能发生的最糟糕的事情包括:

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

我看过他们所有人的报道。

原因是如果线程在使用共享HashMap时没有适当地同步,那么可以有:

  • 由公开竞争条件引起的问题,或
  • 由于各种(允许的)缓存行为导致一个线程看到过时值导致的问题。

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

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

另一答案

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

而不是你应该考虑使用ConcurrentHashMap

以上是关于如果我同时(从多个线程)写入java.util.HashMap会发生什么最糟糕的事情?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以从多个线程写入同一文件的不同部分?

从多个线程写入内存区域会导致争用吗?

同时从多个线程访问只读数据是不是明智?

多个线程同时写入多个文件 - 它正被另一个进程使用

多个线程可以安全地同时将相同的值写入同一个变量吗?

在 C 或 C++ 中的同一个套接字上同时读取和写入