ConcurrentHashMap学习

结构模型


与HashMap不同的是,ConcurrentHashMap中多了一层数组结构
ConcurrentHashMap类中包含两个静态内部类 HashEntry 和 Segment。HashEntry 用来封装映射表的键 / 值对;Segment 用来充当锁的角色,每个 Segment 对象守护整个散列映射表的若干个桶。每个桶是由若干个 HashEntry 对象链接起来的链表。一个 ConcurrentHashMap实例中包含由若干个 Segment对象组成的数组

ConcurrentHashMap 在默认并发级别会创建包含 16个 Segment 对象的数组。每个 Segment 的成员对象 table 包含若干个散列表的桶。每个桶是由 HashEntry 链接起来的一个链表。如果键能均匀散列,每个 Segment 大约守护整个散列表中桶总数的 1/16。

ConcurrentHashMap 的结构示意图:

用分离锁实现多个线程间的并发写操作

这里的加锁操作是针对(键的 hash 值对应的)某个具体的 Segment,锁定的是该 Segment 而不是整个 ConcurrentHashMap。

用 Volatile 变量协调读写线程间的内存可见性

这点成就了:读线程在读取散列表时,基本不需要加锁
由于内存可见性问题,未正确同步的情况下,写线程写入的值可能并不为后续的读线程可见。


只要之前对链表做结构性修改操作的写线程 M 在退出写方法前写 volatile 型变量 count,读线程 N 在读取这个 volatile 型变量 count 后,就一定能“看到”这些修改。所以读线程在读取散列表时,基本不需要加锁就能成功获得需要的值

总结

在使用锁来协调多线程间并发访问的模式下,减小对锁的竞争可以有效提高并发性。有两种方式可以减小对锁的竞争:

  • 减小请求 同一个锁的 频率。
  • 减少持有锁的 时间。

ConcurrentHashMap 的高并发性主要来自于三个方面:

  • 用分离锁实现多个线程间的更深层次的共享访问。使用分离锁,减小了请求同一个锁的频率。
  • 通过 HashEntery 对象的不变性及对同一个 Volatile 变量的读 / 写来协调内存可见性,使得读操作大多数时候不需要加锁就能成功获取到需要的值。
  • 通过对同一个 Volatile 变量的写 / 读访问,协调不同线程间读 / 写操作的内存可见性。

参考文章探索 ConcurrentHashMap 高并发性的实现机制

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容