探索 ConcurrentHashMap 高并发性的实现机制https://www.ibm.com/developerworks/cn/java/java-lo-concurrenthashmap/
上面的链接已经是比较老的jdk中的了,jdk1.7中代码已经和这个不一样了
1.ConcurrentHashMap 类中包含这两个静态内部类 HashEntry 和 Segment。
HashEntry 用来封装映射表的键 / 值对;
Segment 用来充当锁的角色,每个 Segment 对象守护整个散列映射表的若干个桶。
每个桶是由若干个 HashEntry 对象链接起来的链表。
一个 ConcurrentHashMap 实例中包含由若干个 Segment 对象组成的数组。
2.相比较于
HashTable 和由同步包装器包装的 HashMap
每次只能有一个线程执行读或写操作,
ConcurrentHashMap 在并发访问性能上有了质的提高。在理想状态下,(默认情况配置)ConcurrentHashMap 可以支持 16 个线程执行并发写操作(如果并发级别设置为 16),及任意数量线程的读操作。3.ConcurrentHashmap 的jdk文档:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html
HashMap结构示意图:
1.put
- 对segment加锁
- 通过hash值计算出要插入的insert key值应该在的segment
- 根据hash找到inserkey对应的bucket
- 首先会先遍历bucket的链表,寻找bucket中是否有相同的key
- 如果能找到则直接更新oldvalue
- 如果对应的bucket不存在则创建bucket,把insert key插入到第一个位置
- 如果bucket存在,insert key在bucket中不存在,还是把insert key插入到第一个位置
2.remove
- 对segment加锁
- 找到要删除的key所在的bucket位置
- 遍历链表找到key在链表中的位置
- 用pred纪录便利过记录中最新的一条,也就是用来保存deletekey前面一条记录
- 删除操作具体是用pred->next = e.next
在执行 remove 操作时,原始链表并没有被修改,也就是说:读线程不会受同时执行 remove 操作的并发写线程的干扰。