HashMap source code analyze/ Hashmap/Hashtable/ConcurentHashmap/synchronizedMap
来源:互联网 发布:js获取html标签属性值 编辑:程序博客网 时间:2024/05/22 03:14
Hashmap/Hashtable/ConcurentHashmap/synchronizedMap
http://my.oschina.net/chape/blog/212075Hashtable提供了一种易于使用的、线程安全的、关联的map功能。 然而,线程安全性是凭代价换来的——Hashtable的所有方法都是同步的。synchronized是针对整张Hash表的,即每次锁住整张表让线程独占,安全的背后是巨大的浪费。
HashMap提供一个不同步的基类和一个同步的包装器Collections.synchronizedMap(对应List和Collections.synchronizedList,更安全使用CopyOnWriteArrayList),解决了线程安全性问题。 通过将基本的功能从线程安全性中分离开来,Collections.synchronizedMap是有条件地线程安全——所有单个的操作都是线程安全的,但是多个操作组成的操作序列却可能导致数据争用,因为在操作序列中控制流取决于前面操作的结果。允许需要同步的用户可以拥有同步,而不需要同步的用户则不必为同步付出代价。
ConcurrentHashMap和Hashtable主要区别就是围绕着锁的粒度以及如何锁。
左边便是Hashtable的实现方式---锁整个hash表;而右边则是ConcurrentHashMap的实现方式---锁桶(或段)。 ConcurrentHashMap将hash表分为16个桶(默认值),诸如get,put,remove等常用操作只锁当前需要用到的桶。原来只能一个线程进入,现在却能同时16个写线程进入,并发性的提升是显而易见的。并且ConcurrentHashMap的读取并发,因为在读取的大多数时候都没有用到锁定,所以读取操作几乎是完全的并发操作。
参考:
http://blog.sina.com.cn/s/blog_5157093c0100hm3y.html
http://www.blogjava.net/zlsunnan/archive/2006/07/02/56184.html
SynchronizedMap和ConcurrentHashMap的深入分析
http://blog.sina.com.cn/s/blog_5157093c0100hm3y.html
在开始之前,先介绍下Map是什么?
javadoc中对Map的解释如下:
This interface takes the place of the Dictionary class, which was a totally abstract class rather than an interface.
The Map interface provides three collection views, which allow a map's contents to be viewed as a set of keys, collection of values, or set of key-value mappings.
Map可以使用多种实现方式,HashMap的实现采用的是hash表;而TreeMap采用的是红黑树。
1. Hashtable 和 HashMap
这两个类主要有以下几方面的不同:
- public
static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) { -
new SynchronizedMap<K,V>(m); -
}
该方法返回的是一个SynchronizedMap 的实例。SynchronizedMap类是定义在Collections中的一个静态内部类。它实现了Map接口,并对其中的每一个方法实现,通过synchronized 关键字进行了同步控制。
2. 潜在的线程安全问题
上面提到Collections为HashMap提供了一个并发版本SynchronizedMap。这个版本中的方法都进行了同步,但是这并不等于这个类就一定是线程安全的。在某些时候会出现一些意想不到的结果。
如下面这段代码:
- //
shm是SynchronizedMap的一个实例 - if(shm.containsKey('key')){
-
shm.remove(key); - }
在进行迭代时这个问题更改明显。Map集合共提供了三种方式来分别返回键、值、键值对的集合:
- Set<K>
keySet(); -
- Collection<V>
values(); -
- Set<Map.Entry<K,V>>
entrySet();
- Iterator
keys = map.keySet().iterator(); -
- while(keys.hasNext()){
-
map.get(keys.next()); - }
在这里,有一个地方需要注意的是:得到的keySet和迭代器都是Map中元素的一个“视图”,而不是“副本” 。问题也就出现在这里,当一个线程正在迭代Map中的元素时,另一个线程可能正在修改其中的元素。此时,在迭代元素时就可能会抛出 ConcurrentModificationEx
集合类的 toArray() 方法实现,但是创建副本的方式效率比之前有所降低,特别是在元素很多的情况下;另一种方法就是在迭代的时候锁住整个集合,这样的话效率就更低了。
3. 更好的选择:ConcurrentHashMap
java5中新增了ConcurrentMap接口和它的一个实现类ConcurrentHashMap。ConcurrentHashMap提供了和Hashtable以及SynchronizedMap中所不同的锁机制。Hashtable中采用的锁机制是一次锁住整个hash表,从而同一时刻只能由一个线程对其进行操作;而ConcurrentHashMap中则是一次锁住一个桶。ConcurrentHashMap默认将hash表分为16个桶,诸如get,put,remove等常用操作只锁当前需要用到的桶。这样,原来只能一个线程进入,现在却能同时有16个写线程执行,并发性能的提升是显而易见的。
上面说到的16个线程指的是写线程,而读操作大部分时候都不需要用到锁。只有在size等操作时才需要锁住整个hash表。
在迭代方面,ConcurrentHashMap使用了一种不同的迭代方式。在这种迭代方式中,当iterator被创建后集合再发生改变就不再是抛出ConcurrentModificationEx
- HashMap source code analyze/ Hashmap/Hashtable/ConcurentHashmap/synchronizedMap
- HashMap,ConcurentHashMap,HashTable,Collections.synchronizedMap()线程安全概述
- HashMap、 HashTable 、Collections.synchronizedMap、 ConcurrentHashMap
- HashMap.java source code
- HashMap source code 阅读
- Hashtable, HashMap, Collections.synchronizedMap, ConcurrentHashMap 多线程并发特行分析
- HashMap,HashTable,synchronizedMap,ConcurrentHashMap,TreeMap,IdentityHashMap的比较分析
- Hashtable 和 HashMap和concurrentHashMap和collections.synchronizedMap
- HashTable&HashMap
- HashMap & HashTable
- Hashtable HashMap
- hashmap hashtable
- Hashtable HashMap
- HashMap,Hashtable
- HashTable、HashMap
- HashMap Hashtable
- HashMap & HashTable
- HashMap&HashTable
- poj 3694 Network (连通图缩点+LCA+并查集)
- 杭电1250Hat's Fibonacci
- Podfile.lock: No such file or directory
- Spring与Jedis的集成
- android app 闪退的原因
- HashMap source code analyze/ Hashmap/Hashtable/ConcurentHashmap/synchronizedMap
- C++:STL入门汇总
- 导出mysql数据表
- Java进阶(十一)部分数据类型取值范围
- 在viewController“添加”viewController的方法
- JAVA IO流(1)
- IRP的超时处理
- iOS开发系列--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开发汇总
- 深度学习总结