ConcurrentHashMap详解
一、背景
线程不安全的HashMap
因为多线程环境下,使用HashMap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap。
效率低下的HashTable容器
HashTable容器使用的synchronized来保证线程安全,但是在线程竞争激烈的情况下,HashTable的效率非常低下。因为当一个线程访问HashTable的同步方法时,其他线程访问HashTable的同步方法会进入阻塞或者轮询状态。如果线程1使用put进行添加元素,线程2不但不能使用put方法添加元素,并且不能使用get方法来获取元素,所以竞争越激烈效率越低。
锁分段技术
HashTable容器在竞争激烈的并发环境下表现出效率低下的原因,是因为所有访问HashTable的线程都必须竞争同一把锁,那假如线程里面有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里面不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效提高并发访问效率。这就是ConcurrentHashMap使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁。
源码:
这些是ConcurrentHashMap是最容易做大梅毒名称传播。
我们来看一下ConcurrentHashmap的性能
package com.study.mapdemo; import java.util.Collections; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class TestConcurrentHashMap { public static void main(String[] args) { // TODO Auto-generated method stub final Map<Integer, Integer> hm = Collections.synchronizedMap(new HashMap<Integer, Integer>()); final Map<Integer,Integer> ht = new Hashtable<Integer, Integer>(); final Map<Integer,Integer> chm = new ConcurrentHashMap<Integer, Integer>(); putMap(hm); putMap(ht); putMap(chm); } private static void putMap(final Map<Integer,Integer> map) { long begin = System.currentTimeMillis(); for(int k = 0;k<100;k++) { for(int i = 0;i<1000;i++) { final int key = i; new Thread(new Runnable() { @Override public void run() { for(int j = 0;j<3000;j++) { map.put(key,j); } } }).start(); } } long end = System.currentTimeMillis(); System.out.println(end-begin); } }
代码输出:
22409 21260 15234
可以看到ConcurrentHashMap的性能更高,速度更快。当数据量较大是,ConcurrentHashmap的性能大概是另外两个的3倍左右。