如果我同时(从多个线程)写入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会发生什么最糟糕的事情?的主要内容,如果未能解决你的问题,请参考以下文章