ConcurrentHashMap
是 Java 提供的一个并发散列映射实现,它允许多个线程同时读写而不需要同步整个数据结构。它是线程安全的,并且相比于其他线程安全的 Map 实现(如 Collections.synchronizedMap
或 Hashtable
),它提供了更高的并发性能。
以下是 ConcurrentHashMap
的一些核心特性和相应的源码解释:
- 分段锁 (Segmentation):
- 在 Java 8 之前,
ConcurrentHashMap
使用了分段锁技术来减少线程竞争,即它将数据分为多个段,每个段有其自己的锁。这样,多个线程可以同时操作不同的段而不会产生锁竞争。 - 从 Java 8 开始,
ConcurrentHashMap
使用了一种不同的策略(基于 CAS 操作),并摒弃了分段锁的设计。
- 计算和替换 (compute, merge 等方法):
ConcurrentHashMap
提供了一些原子性的高级更新操作,如compute
、merge
和computeIfAbsent
。
- 扩容 (Resizing):
- 当一个
ConcurrentHashMap
在添加元素时超过了其容量阈值,它会自动进行扩容操作。
以下是与 ConcurrentHashMap
功能相关的源码片段和解释:
putVal 方法
final V putVal(K key, V value, boolean onlyIfAbsent) {
// ...一些检查...
int binCount = 0;
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
if (tab == null || (n = tab.length) == 0)
tab = initTable(); // 初始化表
// ...主要逻辑,包括处理冲突,链表转红黑树等...
}
}
这个方法是 put
操作的主要逻辑,它处理各种情况,例如初始化表、处理键的冲突和链表的转换。
getNode 方法
final Node<K,V> getNode(int hash, Object key) {
// ...一些检查...
for (Node<K,V> e = tabAt(tab, i = (n - 1) & hash); e != null; e = e.next) {
// ...遍历链表或树来查找键...
}
}
这个方法用于获取一个具有给定哈希值和键的节点。它首先计算键的位置,然后遍历链表或树来查找。
resize 方法
这是扩容操作的核心,当 ConcurrentHashMap
增长并超过其容量阈值时,将调用此方法。扩容可以提高查找效率,因为它减少了冲突。
这只是 ConcurrentHashMap
的冰山一角。为了全面了解其实现细节,建议您深入查看其源代码和相关的 Javadoc。