一、回首往事-HashMap
回顾HashMap的结构:
HashMap是一个Entry对象的数组。
数组中的每一个Entry元素,又是一个【链表】的【头节点】
HashMap不是【线程安全的】,在高并发环境下做【插入操作】,有可能出现【环形链表】。
二、避免HashMap的线程安全问题方法
1、使用Hashtable
2、Collections.synchronizedMap()
但是,这两者有着共同的问题:【性能】
无论是读操作还是写操作,它们都会给整个集合加锁,导致同一时间的其他操作为之阻塞。
在【并发】环境下,如何能兼顾【线程安全】和【运行效率】呢?
这时候ConcurrentHashMap就运营而生了
三、ConcurrentHashMap最关键要理解【Segment】
①. Segment本身就相当于一个HashMap对象。
②. 同HashMap一样,Segment包含一个Entry数组,数组中的每一个Entry既是一个键值对,也是一个链表的头节点。
③. 单一的Segment结构如下:
像这样的Segment对象,在ConcurrentHashMap集合中有多少个呢?
2的N次方个,共同保存在一个名为segments的数组中。
因此整个ConcurrentHashMap的结构如下:
可以说,ConcurrentHashMap是一个【二级哈希表】,
在一个总的哈希表下面,有若干个子哈希表。
这样的二级结构,和数据库的水平拆分有些相似。
这样的设计有什么好处呢?
ConcurrentHashMap优势是采用了【锁分段】技术,每一个 Segment就好比一个自治区,读写操作高度自治,Segment之间互不影响。
四、ConcurrentHashMap并发读写几种情形
Case1:不同Segment的并发写入
Case2:同一Segment的一写一读
Case3:同一Segment的并发写入