2

HashMap is not thread safe.

In my case: 1 writer thread to update the HashMap, and N reader thread to read from the HashMap.

I found tha there is only 1 bad case :

  1. reader N read a value V1
  2. writer update V1 to V2
  3. reader N use value V1(but it is V2 now )

if in my business , we can tolerate this case, is there any other bad case?

4

5 回答 5

4

如果读者会迭代HashMap并同时被作者修改,则可能会出现更严重的问题。通常对此类集合的修改(在 C# 或 Python 等其他语言中)会使其所有迭代器无效。

文档中:

请注意,此实现不同步。如果多个线程同时访问一个哈希映射,并且至少有一个线程在结构上修改了映射,则它必须在外部同步。(结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。)

于 2013-08-04T13:19:59.137 回答
1

您提到的情况并不是真正的问题,因为如果 HashMap 是线程安全的,可能会发生同样的事情。如果 V2 在 V1 正在进行更改时从 HashMap 读取数据,则可能会遇到麻烦。此时HashMap的内部状态是不一致的。这可能会导致 V2 的程序在没有明显原因的情况下神秘地崩溃。

于 2013-08-04T13:23:05.083 回答
1

没有适当的同步有两个问题。一是visibility and原子性`。假设您有地图,并且在一个线程中增加了值。比其他线程可能会看到一个陈旧的值。类似地,如果一个线程已经放置了 K、V,那么另一个线程可能看不到它。同样,迭代也会受到影响。

因此,对于safe publication问题,visibility最好使用 ConcurrentHashMap 来lock striping获得更好的并发性。但是对于我上面提到的增量内容,我们需要使用外部同步。

如果我们不更改value(K)orkey (K)并且我们只是插入到 /getting 从HashMap然后将键和值类作为immutable类,我们可以做的最好的事情。重要的是声明HashMapfinal. 这将照顾happens before关系,问题就会消失。谢谢。

于 2013-08-04T13:26:55.383 回答
0

好吧,如果你问在这种情况下会发生什么,那么我们首先应该理解的是,当一个类被记录为 NOT THREAD SAFE 时,所有这些坏事都可能发生,这通常发生在非线程安全的类中。现在,非线程安全类会发生什么,它不会按照合同正确运行。这意味着如果您调用 get(Key) ,它可能不会返回正确的值。而非线程安全类的这种行为归因于 ATOMICITY 和 VISIBILTY。

底线是,如果一个类不是线程安全的,你就不能指望它的契约或暴露的特性。

于 2013-08-05T02:41:33.477 回答
0

当读者在其中搜索时,作者可以修改 HashMap 的内部结构,从而导致随机行为(错误的值、空值而不是值、异常)。此外,更改可能永远不会传播到其他线程,而不会告诉 jvm 期望多线程访问,更新永远不会在多个 cpu 内核上同步,或者 jvm 只是将它们优化为 noop。

在您的情况下,您可以使用 ReadWriteLock 来确保所有读者可以同时访问地图,而作者拥有独占访问权限。

于 2013-08-04T13:42:32.410 回答