多线程(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 可以帮助开发者构建高性能的并发应用。

相关推荐
IT_陈寒13 分钟前
Python高手都在用的5个隐藏技巧,让你的代码效率提升50%
前端·人工智能·后端
Qiuner36 分钟前
Spring Boot 机制二:配置属性绑定 Binder 源码解析(ConfigurationProperties 全链路)
java·spring boot·后端·spring·binder
Victor35636 分钟前
Redis(151)Redis的内存使用如何监控?
后端
Victor35636 分钟前
Redis(150)Redis的性能瓶颈如何排查?
后端
豆浆whisky2 小时前
Go并发模式选择指南:找到最适合你项目的并发方案|Go语言进阶(19)
开发语言·后端·golang
Y***h1879 小时前
第二章 Spring中的Bean
java·后端·spring
稚辉君.MCA_P8_Java10 小时前
DeepSeek 插入排序
linux·后端·算法·架构·排序算法
t***p93510 小时前
idea创建SpringBoot自动创建Lombok无效果(解决)
spring boot·后端·intellij-idea
d***817210 小时前
解决SpringBoot项目启动错误:找不到或无法加载主类
java·spring boot·后端
无限大610 小时前
RBAC模型:像电影院选座一样管理权限,告别"一个用户配一个权限"的噩梦
后端