ConcurrentHashMap和 Hashtable 的区别主要体现在实现线程安全的方式上不同
底层数据结构:
1、JDK1.7的 ConcurrentHashMap底层采用分段的数组+链表实现,JDK1.8采用的数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树。
2、HashTable和 JDK1.8之前的 HashMap 的底层数据结构类似,都是采用数组+链表的形式,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的;
实现线程安全的方式(重要):
1、在 JDK1.7的时候,ConcurrentHachMap(分段锁)对整个桶数组进行了分割分段(Segment),每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率。
到了JDK1.8的时候已经摒弃了Segment的概念,而是直接用 Node 数组+链表+红黑树的数据结构来实现,并发控制使用synchronized和CAS来操作。(JDK1.6以后对synchronized锁做了很多优化)整个看起来就像是优化过且线程安全的 HashMap,虽然在JDK1.8中还能看到 Segment的数据结构,但是已经简化了属性,只是为了兼容旧版本;
2、HashTable(同步锁):使用synchronized来保证线程安全,效率非常低下。当一个线程访问同步方法时,其他线程也访问同步方法,可能会进入阻塞或轮询状态,如使用 put添加元素,另一个线程不能使用put添加元素,也不能使用get,竞争会越来越激烈效率越低。
总结:
1、HashTable就是实现了HashMap 加上了 synchronized,而ConcurrentHashMap底层采用分段的数组+链表实现,线程安全
2、ConcurrentHashMap 通过把整个Map分为N个Segment,可以提供相同的线程安全,但是效率提升N倍,默认提升16倍。并且读操作不加锁,由于 HashEntry 的value变量是 volatile的,也能保证读取到最新的值。
3、Hashtable的synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,ConcurrentHashMap 允许多个修改操作并发进行,其关键在于使用了锁分离技术
4、扩容:段内扩容(段内元素超过该段对应Entry数组长度的75%触发扩容,不会对整个Map进行扩容),插入前检测需不需要扩容,有效避免无效扩容

Was this helpful?

0 / 0

发表回复 0

Your email address will not be published.