java - ConcurrentHashMap 完全安全吗?

标签 java multithreading synchronized java.util.concurrent

这是一段来自 JavaDoc 关于 ConcurrentHashMap 的文章。它说检索操作通常不会阻塞,因此可能与更新操作重叠。这是否意味着 get() 方法不是线程安全的?

"However, even though all operations are thread-safe, retrieval operations do not entail locking, and there is not any support for locking the entire table in a way that prevents all access. This class is fully interoperable with Hashtable in programs that rely on its thread safety but not on its synchronization details.

Retrieval operations (including get) generally do not block, so may overlap with update operations (including put and remove). Retrievals reflect the results of the most recently completed update operations holding upon their onset."

最佳答案

get()方法是线程安全的,其他用户为您提供了有关此特定问题的有用答案。

然而,虽然ConcurrentHashMapHashMap 的线程安全插入替代品,重要的是要意识到,如果您正在执行多项操作,您可能必须显着更改您的代码。比如下面这段代码:

if (!map.containsKey(key)) 
   return map.put(key, value);
else
   return map.get(key);

在多线程环境中,这是一种竞争条件。您必须使用 ConcurrentHashMap.putIfAbsent(K key, V value) 并注意返回值,它告诉你 put 操作是否成功。阅读文档了解更多详情。


回答要求澄清为什么这是竞争条件的评论。

假设有两个线程 A , B这将在 map 中放置两个不同的值,v1v2分别具有相同的 key 。 key 最初不存在于 map 中。它们以这种方式交错:

  • 话题 A来电containsKey并发现 key 不存在,而是立即挂起。
  • 话题 B来电containsKey发现key不存在,有时间插入它的值v2 .
  • 话题 A简历和插入 v1 ,“和平地”覆盖(因为 put 是线程安全的)线程插入的值 B .

现在讨论 B “认为”它已经成功插入了自己的值v2 ,但 map 包含 v1 .这真是一场灾难,因为线程 B可调用v2.updateSomething()并且会“认为” map 的消费者(例如其他线程)可以访问该对象,并且会看到可能重要的更新(“例如:此访问者 IP 地址正在尝试执行 DOS,从现在开始拒绝所有请求”)。相反,该对象将很快被垃圾收集并丢失。

关于java - ConcurrentHashMap 完全安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14947723/

相关文章:

java - 使用执行器服务等待守护线程完成迭代

java - 这个程序实际上是如何运作的?

java - 在露天。如何创建临时文件进行测试?

java - 使用 Chrome 进行调试时,GWT 开发人员插件会提示

java - 同步 HashMap 访问

java - 我需要使 Singleton 类中的每个方法同步吗?

java - 在 Java 中测试 while 循环中的条件然后退出 while 循环

Java Servlets - 使用公共(public)定时器阻塞所有线程

没有 pthreads 的 C 多线程 : "The program no longer exists" Seg fault

java - 锁和嵌套的同步方法