Java------ConcurrentHashMap简介

ConcurrentHashMap

相比较于HashMap和HashTable,比HashMap更安全,在多线程情况下不会出现死循环,比HashTable的效率更高,HashTable每一次都加了synchronized锁,导致多线程的竞争过于激烈。而ConcurrentHashMap使用了锁分段技术来提升并发效率。

锁分段技术

就是将锁用于容器的一部分数据,多个锁加锁于多个数据,这样这个数据加锁,不会影响其他部分数据加锁。获取这段数据和其他数据就不会出现因为整体加锁而出现竞争的情况。

ConcurrentHashMap的结构

ConcurrentHashMap是由一个Segment和毅哥HashEntry组成的,Segment是一种可重入锁(ReentranLock),作为锁存在于ConcurrentHashMap,而HashEntry则是存着键值对。
在ConcurrentHashMap中的Segment相当于一个HashMap,由数组和链表组成。数组存着Segment锁。对应数组的链表里面是HashEntry存着数据。所有在获取HashEntry的时候,必须先回去Segment,获得锁,再在对应的链表中获得HashEntry的数据。

ConcurrentHashMap的操作

1、get操作
Segment的get操作,先经过一次散列,然后通过散列运算把这个值定位到Segment,在通过散列算法定位到元素。

public V get (Object key) {
       int hash = hash(key.hashCode());
       return segmentFor(hash).get(key, hash);
}

ConcurrentHashMap的get操作十分高效,因为get读操作并没有加锁。ConcurrentHashMap把共享变量全部使用volatile修饰,保证读到的值是最新值。因为volatile的happen before原则,写操作先于读操作。保证了2个变量同时修改get的值,两个变量也能同时读到最新的值。

transient volatile int count;
volatile V value

2、put操作
put操作需要对共享变量使用写操作,所以需要加锁。put操作首先定位到segment然后在segment进行写操作,但是在写之前需要进行2个操作,确定hashentry是否需要扩容,如果扩容扩多大,然后在将元素放到他定位的位置。

对于扩容,ConcurrentHashMap,会扩容成原来数组的2倍。然后将之前的数组重新散列,然后在将新的数据插入。为了提高效率,ConcurrentHashMap不会全部扩容,这针对当前segment内的数组进行扩容。

3、size操作
获取ConcurrentHashMap的大小,必须统计所有segment里面元素的多少,segment里面的全局变量count就是一个volatile修饰的。但是不能直接所有count相加得到,万一在加之后出现了变化就会有误。
但是一般情况下count的数不会变化,如果所有都加锁的话,效率又太低了。
于是ConcurrentHashMap就是先直接统计2个Coutn的和,如果没有变化就直接得出。但是如果其中一次发生了变化则使用加锁的方式来获得size的大学。
而ConcurrentHashMap用来发现容器的变化的东西是使用了modCount变量。如果发生了put、remove、clean方法。modCount都会+1,size通过比较modCount来判断是否发生了变化,从而觉得是否加锁获得size。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值