HashMap
不是线程安全的。
在我的情况下:1个作者线程更新HashMap
和N
读者线程以从HashMap
读取。
我发现只有一个不好的案例:
如果在我的事业中,我们可以容忍这种情况,还有其他不好的情况吗?
答案 0 :(得分:4)
如果读者将遍历HashMap
并且同时它将被作者修改,则可能发生更严重的问题。通常,修改此类集合(使用其他语言,如C#或Python)会使其所有迭代器失效。
请注意,此实现未同步。 如果多个线程同时访问哈希映射,并且至少有一个线程在结构上修改了映射,则必须在外部进行同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。)
答案 1 :(得分:1)
你提到的案例并不是真正的问题,因为如果HashMap是线程安全的,那么同样的事情就会发生。你可能遇到麻烦的地方是,当V1正在进行更改时,V2从HashMap读取。那时,HashMap的内部状态不一致。这可能导致V2的程序神秘地崩溃,没有明显的理由。
答案 2 :(得分:1)
没有正确同步,有两个问题。一个是visibility and
原子性。
假设您有映射,并且在一个线程中您正在递增该值。可能其他线程可能会看到陈旧的值。类似地,如果一个线程已经放置了K,V,则其他线程可能无法看到它。同样,迭代也会受到影响。
因此对于safe publication
,visibility
问题更好地使用ConcurrentHashMap,它使用lock striping
来获得更好的并发性。但是对于我上面提到的增量内容,我们需要使用外部同步。
如果我们不更改value(K)
或key (K)
并且我们只是插入/来自HashMap
,那么我们可以做的最好的事情是将密钥和值类设为{{ 1}}类。并且重要的是将immutable
声明为HashMap
。这将处理final
关系,问题将消失。感谢。
答案 3 :(得分:0)
当读者在其中搜索时,编写者可以修改HashMap的内部结构,从而导致随机行为(错误的值,null而不是值,异常)。此外,更改可能永远不会传播到其他线程而没有任何告诉jvm期望多线程访问,更新永远不会在多个CPU内核上同步,或者jvm只是将它们优化为noop。
在您的情况下,您可以使用ReadWriteLock确保所有读者可以在作者具有独占访问权的同时访问地图。
答案 4 :(得分:0)
好吧,如果你问的是在这种情况下会发生什么,那么我们应该首先理解的是,当一个类被记录为NOT THREAD SAFE时,那么所有那些不好的事情都会发生,这通常发生在非线程安全的情况下类。现在非线程安全类会发生什么,根据它的合同,它将无法正常运行。这意味着如果你调用get(Key),它可能不会返回正确的值。非线程安全类的这种行为归因于ATOMICITY和VISIBILTY。
最重要的是,如果一个类不是线程安全的,那么你就不能指望它的合同或暴露的功能。