文章目录
一、引言
ConcurrentHashMap是Java并发包中的重要成员,它通过巧妙的分段锁设计,实现了高效的线程安全集合。与HashMap相比,它能够支持并发访问;与HashTable相比,它提供了更好的并发性能。
二、基本原理
ConcurrentHashMap采用了分段锁的设计思想,在JDK 1.8中使用CAS和synchronized来实现并发控制。它将数据分散到多个段(Segment)中,每个段都是一个独立的锁,这样不同段的数据可以并发访问。
2.1 数据结构
public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
implements ConcurrentMap<K,V>, Serializable {
// 存储数据的数组
transient volatile Node<K,V>[] table;
// 节点类定义
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
volatile V val;
volatile Node<K,V> next;
Node(int hash, K key, V val, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.val = val;
this.next = next;
}
}
// 树节点类定义
static final class TreeNode<K,V> extends Node<K,V> {
TreeNode<K,V> parent;
TreeNode<K,V> left;
TreeNode<K,V> right;
TreeNode<K,V> prev;
boolean red;
TreeNode(int hash, K key, V val, Node<K,V> next) {
super(hash, key, val, next);
}
}
}
2.2 初始化过程
ConcurrentHashMap的初始化是延迟进行的,只有在第一次插入数据时才会真正初始化table数组:
public class ConcurrentHashMapInit {
// 初始化table数组
private final Node<K,V>[] initTable() {
Node<K,V>[] tab; int sc;
while ((tab = table) == null || tab.length == 0) {
if ((sc = sizeCtl) < 0)
Thread.yield(); // 其他线程正在初始化,让出CPU
else if (U.compareAndSwapInt(this, SIZECTL