JDK提供了一些线程安全的集合。
有粗粒度 synchronized 的集合。如,Hashtable、Collections.synchronizedXxx 包装的集合。
有细粒度,基于分离锁实现的集合。如,ConcurrentHashMap。
通常,并发包中提供的容器性能远优于早期的简单同步实现。
为什么需要ConcurrentHashMap?
HashMap 不是线程安全的。在并发场景中,可能会出现类似CPU占用100%之类的问题(死循环)。
Hashtable 和 Collections.synchronizedMap() 包装的HashMap:
内部都是通过 synchronized 同一把锁,来同步所有并发操作(put、get、size 等)。
这导致一个线程在操作时,其它线程只能等待,并发效率低。
它们只适合在并发程度较低的场景下使用。
ConcurrentHashMap 如何做到高效地线程安全?
ConcurrentHashMap 的设计实现一直在演化。不同JDK版本中的实现可能有较大改动。
Java 7
分离锁。内部分段(Segment,继承自ReentrantLock),段内是HashEntry数组,hash值相同的条目以链表形式存放。
HashEntry 内部用 volatile 的 value 字段保证可见性。利用Unsafe提供的底层能力优化性能。
Segment 的数量默认为16,可在相应的构造方法中指定(concurrencyLevel)。
并发操作时,只需锁定相应段,避免整体同步,以提高性能。
PUT:先对key的hash值再次hash,以减少hash冲突。然后利用Unsafe获取相应的Segment,再进行线程安全的put操作。
GET:需要可见性保证,没有同步逻辑。
Java 8 开始
- 总体结构与HashMap相似:桶数组(Buckets) + 内部链表(bin),同步粒度更细。
- 保留Segment定义,但仅用于保证序列化兼容性,不再有任何结构上的用处。
- 不再使用Segment后,初始化操作简化,改为 lazy-load 形式,减小初始化开销。
- size() 方法还是采用分而治之的算法。但使用了内部类 CounterCell(基于 LongAdder 和 Striped64)
- 使用 synchronized 作同步。因为 synchronized 已被优化,无需过分担心性能;内存消耗比 ReentrantLock 少。
- 更多地使用CAS等底层技术实现无锁化并发操作(Unsafe、AtomicReference等)
如,利用 volatile 字段 sizeCtl 来实现互斥
pivate final Node<K, V>[] initTable() { Node<K,V>[] tab; int sc; while ((tab = table) == null || tab.length == 0) { if ((sc = sizeCtl) < 0) // 存在多线程冲突,需等待 Thread.yield(); else if (U.compareAndSetInt(this, SIZECTL, sc, -1)) { // CAS 成功,进入真正的初始化逻辑 ... } } return tab; }
相关推荐
Java-concurrent-collections-concurrenthashmap-blockingqueue.pdf
java源码剖析-ConcurrentHashMap
Java 7_ConcurrentHashMap.jpg
ConcurrentHashMap使用了分段锁(Segment)来实现并发的读写操作,每个Segment都相当于一个小的HashMap,将整个哈希表分成多个部分。这样可以同时进行多个线程的并发读写操作,不会阻塞其他线程的访问。 需要注意的...
Java 多线程与并发(13_26)-JUC集合_ ConcurrentHashMap详解
java7-8中的 HashMap和ConcurrentHashMap全解析
阿里面试题:ConcurrentHashMap为什么是线程安全的? ConcurrentHashMap,其实是线程安全的HashMap,所以阅读ConcurrentHashMap,建议 先阅读一下两篇介绍HashMap的文章 你真的懂大厂面试题:HashMap吗? jdk1.7 ...
java7-8中的 HashMap和ConcurrentHashMap全解析 如果你想了解底层的逻辑就来看看吧
Java——并发容器之ConcurrentHashMap;Java——并发容器之ConcurrentHashMap;Java——并发容器之ConcurrentHashMap;Java——并发容器之ConcurrentHashMap;Java——并发容器之ConcurrentHashMap;Java——并发...
介绍完整的,算是个开胃菜吧,类似CAS等更加底层的机制,后面会在Java进阶模块中的并发主题有更加系统的介绍。知识扩展1. 为什么需要 ConcurrentHa
Java利用ConcurrentHashMap实现本地缓存demo; 基本功能有缓存有效期、缓存最大数、缓存存入记录、清理线程、过期算法删除缓存、LRU算法删除、获取缓存值等功能。 复制到本地项目的时候,记得改包路径哦~
Java并发编程之ConcurrentHashMap Java并发编程之ConcurrentHashMap.pdf
Java concurrency集合之ConcurrentHashMap_动力节点Java学院整理,动力节点口口相传的Java黄埔军校
ConcurrentHashMap是一个线程安全的HashTable,它的主要功能是提供了一组和HashTable功能相同但是线程安全的方法。ConcurrentHashMap可以做到读取数据不加锁,并且其内部的结构可以让其在进行写操作的时候能够将锁的...
HashTable是一个线程安全的类,它使用synchronized来锁住整张Hash表来实现线程安全,即每次锁住整张表让线程独占,相当于所有线程进行读写时都去竞争一把锁,导致效率非常低下。ConcurrentHashMap可以做到读取数据不...
java本地缓存ConcurrentHashMap
主要介绍了Java中遍历ConcurrentHashMap的四种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
... 5. InheritableThreadLocal作用和实现方式 ?...9. HashMap为什么线程不安全 10. HashMap在jdk7和8中的区别 11. HashMap 为啥将链表改成红黑树? 12. ConcurrentHashMap在jdk7和8中的区别? ...
第一步是用单线程构建一个2倍容量的nextTable 第二步就是用多线程去遍历table里面所有的Node 第三步,当所有数据都复制到nextTable之后,将