ConcurrentHashMap
来源:互联网 发布:织梦cms如何仿站 编辑:程序博客网 时间:2024/06/07 06:59
ConcurrentHashMap:重要:1)ConcurrentHashMap使用了多个锁来控制对hash表的不同段(Segment)进行修改(即锁分离技术),每个段其实就是一个小的 hash table,它们都有自己各自的的锁。只要多个修改操作发生在不同的段上,它们就可以并发进行。2)Segment锁是一种可重入锁ReentrantLock,在ConcurrentHashMap里扮演锁的角色。3)一个ConcurrentHashMap里包含一个Segment数组,Segment的结构其实就是一个小的hash table。一个Segment里包含一个HashEntry数组,当对HashEntry数组的数据进行修改时,必须首先获得它对应的Segment锁。4)ConcurrentHashMap中Segment的数量一经指定,不可改变。如果需要扩容,那么只会对Segment中的链表数组进行扩容,所以扩容过程不需要对整个ConcurrentHashMap做rehash,而只需要对Segment里面的元素做一次rehash就可以了。--------------------1)get方法:特点:简单和高效。首先调用传入的Key的hashCode()方法,返回的hashCode用于找到对应的segment的位置,然后调用Segment的get(key, hash)方法,通过哈希算法找到对应的元素public V get(Object key) {int hash = hash(key.hashCode());return segmentFor(hash).get(key, hash);}高效:整个get过程不需要加锁(注:当值为null时,才会加锁去读)原因:get方法中将共享变量都定义成volatile,例如:用于统计当前Segement大小的count字段和用于存储值的HashEntry的value2)put方法:首先调用key的hashCode()方法,返回的hashCode用于找到对应的segment的位置,然后调用Segment的put()方法来储存Entry对象重要:1)多线程环境下,对共享变量进行写入操作时必须得加锁。2)Segment的put方法中使用了可重入锁。 public V put(K key, V value) { if (value == null) throw new NullPointerException(); int hash = hash(key.hashCode()); return segmentFor(hash).put(key, hash, value, false); }3)size方法:1)ConcurrentHashMap的大小就是全部Segment的count之和。2)在累加count的过程中,已经累加过的count发生变化的几率很小,3)ConcurrentHashMap先以不锁住Segment的方式来统计各个Segment的大小,以这样的方式统计2次,如果2次统计的count不一致,则再采用加锁的方式来统计所有Segment的大小。4)ConcurrentHashMap使用modCount变量,在put、remove和clean方法中操作元素前都会将modCount加1,比较modCount的值在统计前后是否一致来判断segment的大小是否发生变化。// ConcurrentHashMap部分源码(jdk1.6)public class ConcurrentHashMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>, Serializable { final Segment<K,V>[] segments; transient Set<K> keySet; transient Set<Map.Entry<K,V>> entrySet; transient Collection<V> values; static final class Segment<K,V> extends ReentrantLock implements Serializable {transient volatile HashEntry<K,V>[] table;// 当前Segement的大小,即包含HashEntry的数量 transient volatile int count;// table被更新的次数。注:在put、remove和clean方法中操作元素前都会将modCount加1transient int modCount;// ...} static final class HashEntry<K,V> { final K key; final int hash; volatile V value; final HashEntry<K,V> next; HashEntry(K key, int hash, HashEntry<K,V> next, V value) { this.key = key; this.hash = hash; this.next = next; this.value = value; }// ... } public V get(Object key) { int hash = hash(key.hashCode()); return segmentFor(hash).get(key, hash); } public V put(K key, V value) { if (value == null) throw new NullPointerException(); int hash = hash(key.hashCode()); return segmentFor(hash).put(key, hash, value, false); }}
0 0
- ConcurrentHashMap
- ConcurrentHashMap
- ConcurrentHashMap
- ConcurrentHashMap
- ConcurrentHashMap
- ConcurrentHashMap
- ConcurrentHashMap
- ConcurrentHashMap
- ConcurrentHashMap
- ConcurrentHashMap
- ConcurrentHashMap
- ConcurrentHashMap
- ConcurrentHashMap
- ConcurrentHashMap
- ConcurrentHashMap
- concurrenthashmap
- ConcurrentHashMap
- ConcurrentHashMap
- Nutz笔记-数据库篇
- Single Number II
- tabbarcontronller
- 交叉验证(Cross Validation)
- 工欲善其事,必先利其器
- ConcurrentHashMap
- eclipse 插件 代码提示 C C++
- 虚拟化三剑客专题-XenServer(上)
- 解决TortoiseGit图标不显示
- ubuntu14.04 安装及配置sublime text 3
- TI(德州仪器) TMS320C674x逆向分析之二
- 一个程序员在北京找工作的感悟-很有感觉
- [每日一答] [20151024] incomplete final line found by readTableHeader on ${fileName}原因以及解决方案
- [每日一答] [20151025] R语言并行计算的原理和案例