码迷,mamicode.com
首页 > 其他好文 > 详细

ConcurrentHashMap

时间:2018-12-18 00:01:24      阅读:183      评论:0      收藏:0      [点我收藏+]

标签:同步代码块   迭代器   执行   添加元素   cep   sync   hash   拆分   遍历   

ConcurrentHashMap中引入了分段锁的概念,可以理解为将一个大的Map拆分成N个小的Hashtable(通过synchronized保证线程安全),被称为segments,根据key.hashCode来决定把key放到哪个Hashtable中。

对于操作同一segment的两个线程,后一个将被阻塞;对于操作不同segment的两个线程,互不影响--以此相对于Hashtable提高效率。ConcurrentHashMap缺省情况下生成16个segments,也就是允许16个线程并发更新而尽量没有阻塞、锁的争用。

HashMap或者ArrayList边遍历边删除会抛异常,因此需要使用Iterator删除元素;ConcurrentHashMap边遍历边删除或增加操作不会产生影响,即使多个线程一起删除、添加元素也没问题。

一个线程对ConcurrentHashMap增加数据,另外一个线程在遍历时就能获得。

get方法不涉及到锁,即获得对象时没有使用锁;

ConcurrentHashMap允许边遍历边更新,即在使用Iterator进行的遍历的时候,可以使用put、remove方法对Map进行更新,若想获得当前的全部数据,可以使用synchronized将ConcurrentHashMap对象包装,在{}进行Iterator操作;

HashMap或ArrayList在边遍历边删除时会报java.util.ConcurrentModificationException异常,不过可以用迭代器解决;

对ConcurrentHashMap边遍历边删除或者增加操作不会产生异常,遍历的时候都能获得最新值,即使多个线程一起删除、添加也没有问题。

但是,ConcurrentHashMap只保证了原子操作的线程安全:
map.put(key, map.get(key) + 1);
以上操作并非原子操作,包含了三个步骤:
1.map.get
2.+1
3.map.put

其中第1步和第3步,单独来说是线程安全的,可以由ConcurrentHashMap保证;如果map是一个共享对象,线程A执行map.get时,线程B可能在执行map.put,则当线程A执行到map.put时,线程A中的数据已经是脏数据,导致线程不安全;

为了保证线程安全,需要使用同步代码块synchronized(共享变量),之后可以将ConcurrentHashMap换成HashMap,检验ConcurrentHashMap是否还有必要。

ConcurrentHashMap

标签:同步代码块   迭代器   执行   添加元素   cep   sync   hash   拆分   遍历   

原文地址:https://www.cnblogs.com/yuanfei1110111/p/10134350.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!