java中map的线程安全问题

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

** 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线程可使用原来老的数据,而写线程也能够并发的完成改变。

相关文章
相关标签/搜索