前言
哈希表的组织形式是这样的:
对于哈希表这种重要而又频繁被使用的数据结构,是否线程安全往往是人们经常考虑的方向之一。
一、HashTable
HashTable是线程安全的。但是它的线程安全在于它的关键方法都使用了synchronized,比如get方法、put方法,这就会导致它的并发程度低下。它就是相当于给整个哈希表使用一把锁:
二、HashMap
HashMap是线程不安全的哈希表,当我们不需要考虑线程安全问题时,HashMap无疑是最优选择。
三、ConcurrentHashMap
ConcurrentHashMap 是线程安全的hash表。给每个哈希桶安排了一把锁:
ConcurrentHashMap的改进:
- (主要)减少了锁的颗粒度,每个链表都有一把锁,大部分情况下都不会涉及锁冲突;
- 广泛使用CAS操作,避免了锁冲突;
- 写操作进行了加锁(哈希桶级别),读操作没加锁;
- 渐进式扩容。当需要扩容时会创建出一个更大的数组,慢慢的把数据往新数组上增加。
渐进式扩容:
- 新增元素,往新数组增加;
- 删除元素,新数组和旧数组都进行寻找然后删除即可;
- 修改元素,新数组和旧数组都进行寻找,然后把该元素写到新数组上;
- 查找元素,新数组和旧数组都进行寻找。
在Java8之前,ConcurrentHashMap 进行了锁分段技术:
目的是为了降低锁竞争的概念(Java8之前的概念)。