HashTable 和 ConcurrentHashMap 的区别

ArrayList、LinkedList、Queue、HashMap、TreeMap、HashSet、TreeSet …都是线程不安全的。 如果多个线程修改同一个 ArrayList(或是其他的),都会出现线程不安全问题。 如果是一个线程修改,则没事。 如果是多个线程读取,也没事。

HashMap 是线程不安全的。 HashTable 和 ConcurrentHashMap 是线程安全的。

HashTable 和 ConcurrentHashMap的区别

多线程环境下使用 哈希表时:

哈希表的结构是 数组 + 链表 / 红黑树。

    HashTable:

HashTable (不推荐)单纯使用一个 sychronized 进行加锁, 具体相当于针对整个 HashTable 对象,坏处就是锁冲突的概率非常高。

    ConcurrentHashMap:

ConcurrentHashMap 内部针对多线程做出了一定的优化。(推荐使用) 1. 并不是针对整个对象加一把锁,而是分成了很多把锁。 每个链表 / 红黑树都分配一把锁。 只有当两个线程恰好修改同一个链表 / 红黑树的时候,才会涉及到锁冲突。 2. 针对读操作,可以直接不加锁。 如果读不加锁,读操作可能会读到一个写之前的值,也可能读到一个写之后的值,还可能读到一个写中间的值。 大部分场景对于读的线程安全操作没有那么高的要求。 3. 内部广泛的使用了CAS 操作,来提高效率。 比如:获取元素个数的时候,没有加锁,直接 CAS 。 修改元素、获取对应的链表的下标的时候,也用 CAS。 4. 针对扩容进行了优化 Hash表的扩容比较麻烦,需要把整张表都拷贝一份。 如果是 HashTable,某个线程 t 正好触发了扩容,那这个线程 t 就要负责完成整个扩容过程。 如果是ConcurrentHashMap,把扩容任务分散开了 。形如“蚂蚁搬家”,一次只扩容一点,由n个线程,每次操作一点每次操作一点。防止只针对一个线程,就可以平滑的进行过渡。

经验分享 程序员 微信小程序 职场和发展