请教我学Java(二)ConcurrentHashMap为什么是线程安全的

HashMap线程不安全

HashMap在扩容的时候会调用resize()方法,这样的并发操作容易在一个桶上形成环形链表。当获取一个不存在的key时,计算出的index正好时环形链表的下标时就会出现如下的死循环。

ConcurrentHashMap线程安全

引入了如下的Segment数组

其中的核心数据,例如value和链表都是由volatile修饰的,保证了数据的可见性。

原理上来说:ConcurrentHashMap 采用了分段锁技术,其中 Segment 继承于 ReentrantLock。不会像 HashTable 那样不管是 put 还是 get 操作都需要做同步处理,理论上 ConcurrentHashMap 支持 CurrencyLevel (Segment 数组数量)的线程并发。每当一个线程占用锁访问一个 Segment 时,不会影响到其他的 Segment。

jdk1.8抛弃了原有的segment锁,而使用CAS(Compare ans Swap) + synchronized的方式实现。