在进行结构性修改,如put/remove/replace时都需要进行加锁,但是读取并未加锁,并发情况下,由于内存不同步问题,会导致一个线程的写操作并不会立即对另一个线程可见。这里ConcurrentHashMap通过volatile变量的内存可见性特性来保证一个线程的写操作立即被其他线程可见,每个方法在一开始都会读取count这个变量,该变量就是一个volatile变量,多个线程之间通过读写这个变量来保证内存可见性,具体可参考下方的关于JVM内存可见性的说明。
ConcurrentHashMap首先通过Segment对整个数据集进行切分,并通过对各个部分的数据集进行加锁来提高整个数据集的并发性;通过读写分离的方式实现无锁读,加锁写,进一步提高ConcurrentHashMap的读写效率;并通过volatile变量的特性实现读写的可见性保证。
使用场景
ConcurrentHashMap由于其即使在同步的情况下依旧保证高效的读写性能,所以在很多需要使用HashMap的情况都适用,当然单线程情况并不需要使用同步的ConcurrentHashMap。如果无法保证你的HashMap只是在单线程情况下使用那么就使用ConcurrentHashMap,因为其在单线程情况下的效率也并不低。
下面是针对单线程环境下ConcurrentHashMap和HashMap的put性能的对比:
硬件PC:普通PC机,i5
JVM:内存1G
测试数据:执行10次,计算均值
结果:表格
Map
PUT1W次
PUT10W次
PUT100W次
ConcurrentHashMap
2175317
28068193
1355076232
HashMap
1201131
28068193
407341713