我是 Java 线程的新手,我需要从几个活动线程访问数据结构。我听说java.util.concurrent.ConcurrentHashMap是线程友好的。synchronized(map){}
访问 ConcurrentHashMap 时是否需要使用它,否则它会自行处理锁?
5 回答
它自己处理锁,实际上您无法访问它们(没有其他选择)
您可以synchronized
在特殊情况下用于写入,但很少需要这样做。例如,如果您需要实现自己的putIfAbsent
,因为创建对象的成本很高。
使用 syncrhonized 进行读取会破坏使用并发集合的目的。
ConcurrentHashMap
仅适用于您不需要比提供的开箱即用更多的原子性的情况。例如,如果您需要获取一个值,对其进行操作,然后设置一个新值,所有这些都在原子操作中,如果没有外部锁定,这是无法实现的。
在所有这些情况下,没有什么可以替代代码中的显式锁,使用此实现而不是基本的HashMap
.
不,你不需要,但是如果你需要依赖内部同步,你应该使用Collections.synchronizedMap
。来自的javadoc ConcurrentHashMap
:
在依赖线程安全但不依赖同步细节的程序中,此类与 Hashtable 完全可互操作。
实际上它不会在整个数据结构上同步,而是在它的子部分(一些桶)上同步。这意味着ConcurrentHashMap
' 的迭代器是弱一致的,并且映射的大小可能不准确。(但另一方面它的 put 和 get 操作仍然是一致的并且吞吐量更高)
简短回答:不,您不需要使用synchronized(map)
.
长答案:
- 提供的所有操作
ConcurrentHashMap
都是线程安全的,您可以调用它们而不必担心锁定 - 但是,如果您需要在代码中进行一些原子操作,您仍然需要在客户端进行某种锁定
除了它提供的并发特性,concurrenthmp还有一个更重要的特性需要注意,那就是故障安全迭代器。使用 CHMP 只是因为他们想在迭代时编辑用于放置/删除的条目集。
是另一个。但 ConcurrentModificationException 可能出现在上述情况下。Collections.synchronizedMap(Map)