java中map的线程安全问题

Map用于存储“key-value”元素对,它将一个key映射到一个而且只能是唯一的一个value。 Map可以使用多种实现方式,HashMap的实现采用的是hash表;而TreeMap采用的是红黑树。

** java.util包提供了大量集合类。其中最常用的集合类有List、Set、Map等。 **

首先,来看下java.util包中Map相关的集合类。Map往下提供了两个接口:ConcurrentMap和SortedMap。ConcurrentMap是java5中新增的线程安全的Map接口;而SortedMap则是支持排序的Map接口。常用的就属Hashtable、HashMap和TreeMap了。另外,java5新增了HashMap的并发版本ConcurrentHashMap。

** Hashtable 和 HashMap **

Hashtable和HashMap都实现了Map接口,但是Hashtable的实现是基于Dictionary抽象类。

在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。 当get()方法返回null值时,即可以表示HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。而在Hashtable中,无论是key还是value都不能为null 。

这两个类最大的不同在于Hashtable是线程安全的,它的方法是同步了的,可以直接用在多线程环境中,Hashtable中采用的锁机制是一次锁住整个hash表,从而同一时刻只能由一个线程对其进行操作;而HashMap则不是线程安全的,在多线程环境中,需要手动实现同步机制。

** 更好的选择:ConcurrentHashMap **

java5中新增了ConcurrentMap接口和它的一个实现类ConcurrentHashMap,ConcurrentHashMap提供了Hashtable不同的锁机制。 ConcurrentHashMap 在默认并发级别会创建包含 16 个 Segment 对象的数组。每个 Segment 的成员对象 table 包含若干个散列表的桶。每个桶是由 HashEntry 链接起来的一个链表。如果键能均匀散列,每个 Segment 大约守护整个散列表中桶总数的 1/16。

在 ConcurrentHashMap 中,线程对映射表做读操作时,一般情况下不需要加锁就可以完成,对容器做结构性修改的操作才需要加锁。相比较于 HashTable 和由同步包装器包装的 HashMap每次只能有一个线程执行读或写操作,ConcurrentHashMap 在并发访问性能上有了质的提高。在理想状态下,ConcurrentHashMap 可以支持 16 个线程执行并发写操作(如果并发级别设置为 16),及任意数量线程的读操作。

在迭代方面,ConcurrentHashMap使用了一种不同的迭代方式。在这种迭代方式中,当iterator被创建后集合再发生改变就不再是抛出ConcurrentModificationException, 取而代之的是在改变时new新的数据从而不影响原有的数据 ,iterator完成后再将头指针替换为新的数据 ,这样iterator线程可以使用原来老的数据,而写线程也可以并发的完成改变。

转载于:https://my.oschina.net/110NotFound/blog/795081

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值