HashMap
首先HashMap肯定是不行的,并没有加解锁操作,一旦多线程同时写的话,直接就会发生覆盖之类的操作
排除HashMap先,主要对比HashTable和ConcurrentHashMap
HashTable vs ConcurrentHashMap
1. 加锁粒度不同
HashTable
HashTable是对整个哈希表进行加锁操作,任何增删改查操作都会触发加锁,也就是锁竞争
这个图比较形象一点,比如你在下标为0,和下标为1的都要插入元素,但是他们其实之间是不会发生冲突的,没有线程安全问题,但是也要竞争一个锁,严重影响效率
ConcurrentHashMap
ConcurrentHashMap是对每一个头节点作为一把锁,每次进行加锁解锁操作都是针对对应链表的头的锁进行加解锁,如下图所示
这是最大最关键最核心的一个区别
2. CAS机制的利用
ConcurrentHashMap比HashTable更充分利用了CAS机制,也就是无锁编程
有的操作如获取元素和更新元素的个数,可以直接用CAS来完成,不毕加锁
CAS同样能保证线程安全,同时比锁更高效
3.优化了扩容策略
HashTable
当元素过多,负载因子超过了0.75时,进行扩容,需要重新申请内存空间,搬运元素(把元素从旧的哈希表删掉,插入到新的哈希表上)
如果元素过多的话,上亿个,搬运的成本就会非常高,导致此次put操作十分卡顿
ConcurrentHashMap
当超过负载因子时并不会一次性搬运所有元素,而是每次都搬运一部分
当put触发扩容时,此时直接创建更大的空间,并不会把所有元素都搬运过去,先搬运一部分
此时相当于存在两份哈希表了同时
此时插入元素,直接往新表上插入 ; 但是删除元素删旧表的 ; 查表新旧表都查
其他的泛型类
补充一下,多线程中很多例如ArrayList ,LinkedList 之类的都无法使用
可以使用Collections.synchrnized()套一下既可以使用