【多线程】多线程(12):多线程环境下使用哈希表
【多线程环境下使用哈希表(重点掌握)】
可以使用类:“ConcurrentHashMap”
★ConcurrentHashMap对比HashMap和Hashtable的优化点
1.优化了锁的粒度【最核心】
//Hashtable的加锁,就是直接给put,get等方法加上synchronized,就是给this加锁,整个哈希表对象就是一把锁,任何一个针对这个哈希表的操作都会触发锁竞争
而ConcurrentHashMap是给每个哈希表中的“链表”进行加锁(将每个链表头都作为一个锁对象),构成多把锁,形成“锁桶”
这可以保证线程安全
这可以大大降低锁冲突的概率(只有同时进行的两次修改,恰好在修改同一个链表上元素时,才会触发锁冲突)
2.引入了CAS原子操作
哈希表有一个size(链表大小)这样的变量,针对像修改size这样的操作,直接借助CAS完成,不会加锁
3.针对读操作,做了特殊处理
上述的加锁,只是针对写操作来加锁
对于读操作,通过volatile以及一些精巧的代码实现,确保读操作不会读到“修改一半的数据”
4.针对哈希表的扩容,进行了特殊的优化,可以令操作更加稳定
普通哈希表扩容,需要创建新的哈希表,把元素都搬运过去,这一系列操作,很有可能就在一次put就完成了,就会令这次put开销很大,耗时长
ConcurrentHashMap进行了“化整为零”,不会在一次操作中进行所有的数据搬运,而是一次只搬运一部分(创建新空间的同时,也保留旧空间),此时后续的每次操作都会触发一部分key的搬运,最终把所有的key都搬运完成
当新旧空间同时存在时:
1.插入操作——直接插入到新的空间中
2.查询/修改/删除,都是需要同时对旧的空间和新的空间进行操作