ConcurrentHashMap与HashTable都是线程安全的,但是其实现机制有所不同,效率也有所不同,其主要区别如下:
HashTable | ConcurrentHashMap(JDK8之前) | ConcurrentHashMap |
---|---|---|
把所有的get、put方法加上锁实现同步 | 把数据分段,每个分段分别加锁,实现同步,提高效率 | 采用CAS算法提高效率 |
CAS(Compare And Swap)算法,比较替换,用一个期望值与当前值比较,如果期望值与当前值相同则用新值替换当前值。这个是并发场景中乐观锁常常使用的算法。
为什么HashMap不是线程安全的?
HashMap在扩容的时候,元素为重新排列(同一个桶里面的元素采用的是头插入法,原来的链表顺序会被倒置),并发场景可能会形成循环链表。
为什么ConcurrentHashMap不能完全替代HashTable
因为ConcurrentHashMap是弱一致性,其get方法没有上锁,会导致get元素的并不是当前并行还未执行完的put的值,读取到的数据并不一定是最终的值,在一些要求强一致性的场景下可能会出错。例如:需要判断当前值是否为A如果不为A则修改为C,但是当前值为B而有个put方法将其更新为A还没执行完,则最终改值就是A,可能会造成后续程序或业务的异常。
参考
ConcurrentHashMap实现原理及源码分析
JDK1.8逐字逐句带你理解ConcurrentHashMap
ConcurrentHashMap能完全替代HashTable吗
HashMap的扩容机制---resize()
hashmap的线程不安全体现在哪里?