ConcurrentHashMap
使用 segment (继承 ReentrantLock) 和 volatile 来保证线程安全性
segment 的数量为 16,每个 segment 中桶(HashEntry[])的数量可以增加,桶中放的是 由 HashEntry 组成的链表;count 表示 segment 中元素的数量, modCount 统计导致结构变化操作的次数(put、remove、replace、clear)
HashEntry 中的 value 变量 和 指向下一个节点的引用变量 next 都是使用 volatile 关键字进行修饰的,以此保证有序性和可见性
- get() 方法不加锁,先找 segemnt 再找 桶
- put() 方法要加锁,插入之前先判断 count 与阈值的关系,有需要的话则进行扩容处理(桶的容量扩容两倍)
put、remove、replace、clear 操作都要加锁
- size() 先尝试两次不加锁的统计各个 segment 中的 count,如果结果不一致,则采用对全部 segment 加锁的方式统计
JDK 1.8 中的 ConcurrentHashMap
使用 synchronized 和 volatile 关键字来保证线程安全
取消 segment ,当桶中 链表 长度大于 8 时,将链表转换为 RBTree
- get()方法不加锁
- put()方法:
如果桶是空的,则初始化桶,并采用 CAS 操作将元素放在链表的首位
如果桶非空,则通过使用 synchronized 锁住 链表的第一个节点(以此来锁住整个桶),再使用 Unsafe 类的 CAS 操作将元素放在链表的末尾
JDK 1。8 中 ConcurrentHashMap 中使用 synchronized 替代 Segment ,使得锁的粒度更加精细,以此提高程序的性能