ConcurrentHashMap
我记得我曾经在HashMap的文章(点击可查看)里说过,HashMap不是线程安全的,在高并发状态下,HashMap调用transfer方法,可能会出现环形链表,导致程序死循环,为了解决这个问题.当然,解决这个问题,可以用Hashtable或者Collections.synchronizedMap,不过,这两种问题都会出现一个新的问题:性能.会造成阻塞.所以,在高并发下,既要保证安全,又要保证性能问题,就产生了ConcurrentHashMap.
当然,以我目前的水平,无法深入了解ConcurrentHashMap.所以,我这里只是简单的说一下ConcurrentHashMap的一些表面知识.
ConcurrentHashMap的key和value都不能为null
例子:
public class ConcurrentHashMapDemo {
public static void main(String[] args) {
ConcurrentHashMap<String, String> cm = new ConcurrentHashMap<String,String>();
cm.put(null, "马");
//cm.put("屁", null);
}
}
key为null:
value为null:
源码:
在put的源码里,会先判断value是否为null,如果是null,就会抛出空指针异常
如果value不为null,就会用key去计算hash值,在计算时,会报空指针异常
高并发时,ConcurrentHashMap怎么保证安全和性能问题
HashMap和ConcurrentHashMap的数据结构
如果看不懂这张图的话,看下面两张图
在ConcurrentHashMap中,一个segment就是一个HashMap对象,而且因为ConcurrentHashMap采用了锁分段技术,所以每一个segment就好比一个自治区,读写操作高度自治,segment之间互不影响,不过由于segment的写入是需要上锁的,因此对同一segment的并发写入会被阻塞.
结论:ConcurrentHashMap当中每个Segment各自持有一把锁。在保证线程安全的同时降低了锁的粒度,让并发操作效率更高。
关于ConcurrentHashMap的get()和put()的一些东西
get方法:
a) 为输入的key做hash运算,得到hash值
b) 通过hash值,定位到对应的segment对象
c) 再次通过hash值,定位到segment当中数组的具体位置
put方法:
1) 为输入的key做hash运算,得到hash值
2) 通过hash值,定位到对应的segment对象
3) 获取可重入锁
4) 再次通过hash值,定位到segment当中数组的具体位置
5) 插入或覆盖hashEntry对象
6) 释放锁
以上这些内容,都说我在网上一些大神的文章里看到的,当然我这里只是说了个表面,如果大家想要深入了解的话,最好去把那些大神们的文章看看.