ConcurrentHashMap - JiyangM/spring GitHub Wiki

1.HashMap 线程不安全。
2.HashTable 效率低下。

HashTable使用synchronized保证线程安全,在线程竞争激烈的情况下效率很低。因为如果一个线程访问HashTable 的synchronized方法,其他线程就要进入阻塞或者轮训状态,既不能读也不能写。

3.ConcurrentHashMap (锁分段,不是同一分段的数据竞争不同的锁,减少了锁竞争)

假如容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术。首先将数据分成一段一段地存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。

jdk1.7中采用Segment + HashEntry的方式进行实现,结构如下:

1.8中放弃了Segment臃肿的设计,取而代之的是采用Node + CAS + Synchronized来保证并发安全进行实现,结构如下:

Java 8的ConcurrentHashMap同样是通过Key的哈希值与数组长度取模确定该Key在数组中的索引。同样为了避免不太好的Key的hashCode设计,它通过如下方法计算得到Key的最终哈希值。不同的是,Java 8的ConcurrentHashMap作者认为引入红黑树后,即使哈希冲突比较严重,寻址效率也足够高,所以作者并未在哈希值的计算上做过多设计,只是将Key的hashCode值与其高16位作异或并保证最高位为0(从而保证最终结果为正整数)。

jdk 1.8 取消了基于 Segment 的分段锁思想,Segment 并发量受Segment 数组大小的限制,改用 CAS + synchronized 控制并发操作,在某些方面提升了性能。并且追随 1.8 版本的 HashMap 底层实现,使用数组+链表+红黑树进行数据存储。

1.8中放弃了Segment臃肿的设计,取而代之的是采用Node + CAS + Synchronized来保证并发安全进行实现,结构如下:

https://www.ibm.com/developerworks/cn/java/java-lo-concurrenthashmap/index.html