ConcurrentHashMap完全安全吗? [英] Is ConcurrentHashMap totally safe?

查看:110
本文介绍了ConcurrentHashMap完全安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

this is a passage from JavaDoc regarding ConcurrentHashMap. It says retrieval operations generally do not block, so may overlap with update operations. Does this mean the get() method is not thread safe?


但是,即使所有操作都是线程安全的,检索
操作也不需要锁定,并且没有任何支持
以阻止所有访问的方式锁定整个表。此类
在依赖于
线程安全但不依赖于其同步细节的程序中,Hashtable可与Hashtable完全互操作。

"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.

检索操作(包括get)通常不会阻塞,所以
可能与更新操作重叠(包括put和remove)。检索
反映了最近完成的更新操作
在结束时的结果。

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()方法是线程安全的,其他用户为您提供了有关此特定问题的有用答案。

The get() method is thread-safe, and the other users gave you useful answers regarding this particular issue.

但是,虽然 ConcurrentHashMap 是一个thr HashMap 的ead-safe drop-in 替代品,重要的是要意识到如果您正在进行多项操作,则可能需要显着更改代码。例如,取以下代码:

However, although ConcurrentHashMap is a thread-safe drop-in replacement for HashMap, it is important to realize that if you are doing multiple operations you may have to change your code significantly. For example, take this code:

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

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

In a multi-thread environment, this is a race condition. You have to use the ConcurrentHashMap.putIfAbsent(K key, V value) and pay attention to the return value, which tells you if the put operation was successful or not. Read the docs for more details.

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

Answering to a comment that asks for clarification on why this is a race condition.

想象一下,有两个线程 A B 将两个不同的值分别放在地图中, v1 v2 分别具有相同的密钥。该键最初不存在于地图中。它们以这种方式交错:

Imagine there are two threads A, B that are going to put two different values in the map, v1 and v2 respectively, having the same key. The key is initially not present in the map. They interleave in this way:


  • 线程 A 调用 containsKey 并发现该密钥不存在,但会立即暂停。

  • 线程 B 调用 containsKey 并发现该密钥不存在,并且有时间插入其值 v2

  • 线程 A 恢复并插入 v1 ,和平覆盖(自 put 是线程安全的)线程插入的值 B

  • Thread A calls containsKey and finds out that the key is not present, but is immediately suspended.
  • Thread B calls containsKey and finds out that the key is not present, and has the time to insert its value v2.
  • Thread A resumes and inserts v1, "peacefully" overwriting (since put is threadsafe) the value inserted by thread B.

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

Now thread B "thinks" it has successfully inserted its very own value v2, but the map contains v1. This is really a disaster because thread B may call v2.updateSomething() and will "think" that the consumers of the map (e.g. other threads) have access to that object and will see that maybe important update ("like: this visitor IP address is trying to perform a DOS, refuse all the requests from now on"). Instead, the object will be soon garbage collected and lost.

这篇关于ConcurrentHashMap完全安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆