多线程(33)ConcurrentHashMap

ConcurrentHashMap 是 Java 并发包中提供的一个线程安全的哈希表实现。与传统的同步容器相比,ConcurrentHashMap 通过一种分段锁的机制实现了更高的并发度。本节将深入探讨其设计原理,结合源码进行分析,并通过代码示例来演示其使用方法。

设计原理

ConcurrentHashMap 的设计理念是将整个哈希表分为若干个段(Segment),每个段都是一个独立的哈希表,并且拥有自己的锁。当进行插入、删除、更新等操作时,只需要锁定对应的段,而不是整个哈希表。这样,当多线程访问不同段的数据时,这些操作就可以完全并行执行,大大提升了并发性能。

结构解析

在 Java 8 之前,ConcurrentHashMap 的内部实际上是由 Segment 数组组成的,每个 Segment 管理着一定范围的哈希桶。每个 Segment 继承自 ReentrantLock,可以独立加锁。在 Java 8 及以后的版本中,ConcurrentHashMap 放弃了 Segment 的设计,改为直接使用 Node 数组加链表和红黑树,但仍然保持了并发访问的能力,主要是通过使用了 CAS 操作和 synchronized 同步块来实现。

java 复制代码
// ConcurrentHashMap 源码片段(简化版本,基于 Java 8+)
class ConcurrentHashMap<K,V> extends AbstractMap<K,V> implements ConcurrentMap<K,V> {
    transient volatile Node<K,V>[] table;

    static final class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        volatile V value;
        volatile Node<K,V> next;

        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }

        public final K getKey()       { return key; }
        public final V getValue()     { return value; }
        public final int hashCode()   { return key.hashCode() ^ value.hashCode(); }
    }
}

操作细节

  • put操作:当插入一个键值对时,首先计算键的哈希值来确定其在表中的位置。如果目标位置还没有节点,它就使用 CAS 操作直接插入。如果目标位置已经有节点了,则锁定该节点,进而更新数据。
  • get操作:读操作一般不需要加锁(在 Java 8 以后),因为节点的 value 是用 volatile 关键字声明的,可以保证可见性。如果在查询过程中遇到了链表或红黑树,就顺着链表或树进行搜索。

代码演示

java 复制代码
import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {
    public static void main(String[] args) {
        ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();

        // 示例:并发插入
        Thread thread1 = new Thread(() -> map.put("key1", "value1"));
        Thread thread2 = new Thread(() -> map.put("key2", "value2"));

        thread1.start();
        thread2.start();

        // 等待线程结束
        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }

        // 获取并打印结果
        System.out.println(map);
    }
}

总结

ConcurrentHashMap 采用了分段锁的设计理念,大大提升了并发性能,在多线程环境下提供了线程安全的哈希表实现。随着 Java 版本的更新,其内部实现有所变化,但目标仍然是为了提供高效的并发访问。正确使用 ConcurrentHashMap 可以帮助开发者构建高性能的并发应用。

相关推荐
itmigrate19 分钟前
Rust 里的所有权误区:不是不写 clone 就叫高性能
开发语言·后端·rust
码事漫谈25 分钟前
Deepseek v5 来了
后端
爱勇宝32 分钟前
你可能成不了技术大佬,然后呢?
前端·后端·程序员
JuiceFS38 分钟前
HeyGen:如何让全球 10+ GPU 集群训练不再等待数据?
人工智能·后端
暧暧内含光1 小时前
Electron 桌面应用打包原理与实战避坑
后端
郭小李1 小时前
spring @PathVariable 注解用法
java·后端·spring
乔旭伟1 小时前
从一次「报错但成功」查起:SQLAlchemy async 的对象过期与 commit 时机
后端
用户360055579002 小时前
Kestrel_VLLM - 22 · MoE FFN 位级镜像收口:整模型逐层 L2 全等达成
后端
前端小万2 小时前
想做个人副业别乱买服务器!我的 5 个月真实开销分享
前端·后端·github
小蒜学长2 小时前
基于 Spring Boot 的英语单词背诵系统的设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端