Java ConcurrentHashMap锁分段机制使用及代码实例

 更新时间:2025年01月03日 14:34:03   作者:学亮编程手记  
ConcurrentHashMap是Java中的一种线程安全的哈希表,通过锁分段机制提高了并发性能,在Java 8中,ConcurrentHashMap引入了CAS操作和更复杂的节点继承结构,进一步优化了并发操作

概述

锁分段机制ConcurrentHashMap

线程安全的hash表 每一段都是一个独立的锁

Java 5.0 在 java.util.concurrent 包中提供了多种并发容器类来改进同步容器的性能。

ConcurrentHashMap 同步容器类是Java 5 增加的一个线程安全的哈希表。对与多线程的操作,介于 HashMap 与 Hashtable 之间。内部采用“锁分段”机制替代 Hashtable 的独占锁。进而提高性能。

此包还提供了设计用于多线程上下文中的 Collection 实现:ConcurrentHashMap、 ConcurrentSkipListMap、 ConcurrentSkipListSet、CopyOnWriteArrayList 和 CopyOnWriteArraySet。当期望许多线程访问一个给定 collection 时, ConcurrentHashMap 通常优于同步的 HashMap,ConcurrentSkipListMap 通常优于同步的 TreeMap。当期望的读数和遍历远远大于列表的更新数时, CopyOnWriteArrayList 优于同步的 ArrayList。

ConcurrentHashMap就是一个线程安全的hash表。我们知道HashMap是线程不安全的,Hashtable加了锁,是线程安全的,因此它效率低。

HashTable加锁就是将整个hash表锁起来,当有多个线程访问时,同一时间只能有一个线程访问,并行变成串行,因此效率低。所以JDK1.5后提供了ConcurrentHashMap,它采用了锁分段机制。

1.8以后底层又换成了CAS,把锁分段机制放弃了。CAS基本就达到了无锁的境界。

详解

ConcurrentHashMap 是 Java 中的一个线程安全的哈希表,它在多线程环境下提供了高效的读取和更新操作。

从 Java 8 开始,ConcurrentHashMap 引入了一种新的机制,称为“锁分段”(Segmentation with Locks),以提高并发性能。

锁分段机制详解

在 Java 8 之前的版本中,ConcurrentHashMap 使用分段锁(Segmentation with Segments)来实现线程安全。每个段相当于一个小型的哈希表,拥有自己的锁。当多个线程访问不同段的数据时,它们可以并发进行,从而减少了锁的竞争。

然而,Java 8 引入的锁分段机制进一步优化了这一点。在新的实现中:

  • CAS 操作ConcurrentHashMap 使用了更多的无锁编程技术,如原子操作(Compare-And-Swap, CAS),来减少锁的使用。
  • Node 继承结构:内部结构由 NodeTreeNodeTreeBin 等类组成,这些类继承自 Node,形成了一个复杂的继承结构。
  • Synchronized 粒度:在某些操作上,如扩容和部分更新操作上,仍然使用了 synchronized 块来保证线程安全。
  • 减少锁的竞争:通过减少锁的使用,ConcurrentHashMap 允许更高的并发性,因为线程可以在没有锁的情况下进行大部分操作。

示例

下面是一个简单的 ConcurrentHashMap 使用示例:

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {
    public static void main(String[] args) {
        // 创建一个 ConcurrentHashMap 实例
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

        // 插入数据
        map.put("One", 1);
        map.put("Two", 2);
        map.put("Three", 3);

        // 读取数据
        System.out.println(map.get("Two")); // 输出 2

        // 并发更新数据
        for (int i = 0; i < 10; i++) {
            int finalI = i;
            new Thread(() -> map.put("Key" + finalI, finalI)).start();
        }

        // 等待所有线程完成
        while (Thread.activeCount() > 1) {
            Thread.yield();
        }

        // 输出更新后的数据
        System.out.println(map.get("Key9")); // 输出 9
    }
}

在这个示例中,我们创建了一个 ConcurrentHashMap 实例,并插入了一些数据。然后,我们启动了多个线程来并发地更新数据。

由于 ConcurrentHashMap 是线程安全的,即使在多线程环境下,这些操作也不会导致数据不一致的问题。

注意事项

  • ConcurrentHashMap 在高并发环境下比 HashtableCollections.synchronizedMap 有更好的性能。
  • ConcurrentHashMap 适用于读多写少的场景。
  • 在使用 ConcurrentHashMap 时,仍然需要注意避免长时间持有迭代器,因为在迭代过程中可能会有结构性修改(如扩容)。

ConcurrentHashMap 是 Java 并发包 java.util.concurrent 中的一个重要组件,它通过锁分段机制提供了高效的并发访问能力。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • EDI中JAVA通过FTP工具实现文件上传下载实例

    EDI中JAVA通过FTP工具实现文件上传下载实例

    这篇文章主要介绍了EDI中JAVA通过FTP工具实现文件上传下载实例,具有一定的参考价值,有需要的可以了解一下。
    2016-11-11
  • Java设计模式中的适配器模式

    Java设计模式中的适配器模式

    这篇文章主要介绍了Java设计模式中的适配器模式,适配器模式(Adapter Pattern)将某个类的接口转换成客户端期望的另一个接口表示,主的目的是兼容性,让原本因接口不匹配不能一起工作的两个类可以协同工作。其别名为包装器
    2022-07-07
  • Java Socket使用加密协议进行传输对象的方法

    Java Socket使用加密协议进行传输对象的方法

    这篇文章主要介绍了Java Socket使用加密协议进行传输对象的方法,结合实例形式分析了java socket加密协议相关接口与类的调用方法,以及服务器、客户端实现技巧,需要的朋友可以参考下
    2017-06-06
  • spring mvc 和ajax异步交互完整实例代码

    spring mvc 和ajax异步交互完整实例代码

    本篇文章主要介绍了spring mvc 和ajax异步交互完整实例代码,简单的AJAX+SpringMVC的异步交互小例子,有兴趣的可以了解一下。
    2017-02-02
  • ibatis结合oracle批量插入三种方法的测评

    ibatis结合oracle批量插入三种方法的测评

    今天小编就为大家分享一篇关于ibatis结合oracle批量插入三种方法的测评,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • 一文搞懂 MyBatis的事务管理机制

    一文搞懂 MyBatis的事务管理机制

    MyBatis是一款优秀的持久层框架,相信很多Java后端开发人员对它都不会陌生。本文将从事务概述、MyBatis实现事务的方式、事务实现源码分析方面详细解析MyBatis的事务管理机制,需要的朋友可以参考下
    2023-05-05
  • Java容器类的深入理解

    Java容器类的深入理解

    本篇文章是对Java容器类进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • SpringBoot Redisson 集成的实现示例

    SpringBoot Redisson 集成的实现示例

    本文主要介绍了SpringBoot Redisson 集成的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-05-05
  • 解决Java中new BigDecimal()的坑

    解决Java中new BigDecimal()的坑

    这篇文章主要介绍了解决Java中new BigDecimal()的坑,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • Java数据结构与算法实现递归与回溯

    Java数据结构与算法实现递归与回溯

    本文主要介绍了Java数据结构与算法实现递归与回溯,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03

最新评论