ConcurrentHashMap 的使用及其原理

       在java中Map中的实现有HashMap、HashTable、LinkedHashMap等,其中最常用的有HashMap和HashTable,那么HashMap为什么很常用呢?因为HashMap的效率更高些,如果不是在多线程的环境下,不考虑线程安全问题,HashMap绝对是首选项,HashMap通过计算hash值实现快速查找的功能,所以查找的效率特别的高,那么HashMap的结构是什么样子的呢?

HashMap就是这种数组加上链表的结构使得查询的速度非常快,也是通过链表的方式解决了hash冲突问题,但是如果通过hash算法得到的值总是同一个那么链表就会非常的长,或者是每次计算的hash的值都不一样,为了解决这些问题问题,在JDK8中,HashMap使用红黑树的数据结构取代了链表机构。

当然也说到了,hashMap会出现线程安全问题,那么谁是线程安全的呢?HashTable是线程安全的,因为hashTable底层使用了synchronized关键字,保证了线程安全问题,但是如果一个线程访HashTable的同步方法时,其它线程也来访问,那么只能进入阻塞或是轮询状态,所以效率非常的低下。那么有没有既线程安全有速度快的Map呢,当然有了,ConcurrentHashMap就是这样的Map,hashTable之所以慢的原因是所有访问HashTable的线程都必须竞争一把锁,无论访问hashTable中的哪些数据都是竞争一把锁,ConcurrentHashMap的巧妙之处就在于把数据分成很多部分,每一部分加一把锁,每个线程访问的数据不同,线程之间就不会存在竞争同一把锁的情况,这就是ConcurrentHashMap的分段锁,既给数据加了锁,保证了数据的安全性,也减少了锁的竞争,提高了性能,那么ConcurrentHashMap的结构又是什么样的呢?

如图所示,ConcurrentHashMap是由Segment数组和hashEntry数组组成,Segment是一种可重入锁,hashEntry则是用来存放键值对的数据的,在每一个ConcurrentHashMap中都包含一个Segment数组,Segment的结构则是类似hashMap的结构,是数组加链表的结构,每一个Segment里都包含一个HashEntry数组,当线程想要处理hashEntry中的数据时,首先要先获得该hashEntry的Segment锁,这样就保证了ConcurrentHashMap中hashEntry里的数据的安全问题,因此ConcurrentHashMap比hashTable的效率更高,比HashMap更加安全,当你既要考虑安全问题又要考虑性能问题时,ConcurrentHashMap是一个不错的选择。

猜你喜欢

转载自blog.csdn.net/wzs535131/article/details/103757651