concurrentHashmap实现原理

concurrentHashmap是java5支持 高并发、高吞吐量的线程安全HashMap实现.java

实现原理:数组

容许多个修改并发进行,关键技术是锁分离。分为多个段(segment)来表示不一样的部分,每一个段就是一个小的hashtable,他们有本身的锁。安全

有些方法须要跨段,好比size()和containsValue(),它们可能须要锁定整个表而而不单单是某个段,这须要按顺序锁定全部段,操做完毕后,又按顺序释放全部段的锁。并发

1:首先看下get操做,一样ConcurrentHashMap的get操做是直接委托给Segment的get方法,直接看Segment的get方法.高并发

读操做并不须要加锁。为了确保读操做可以看到最新的值,将value设置成volatile,这避免了加锁。spa

            static final class HashEntry<K,V> {  线程

                  final K key;  指针

                  final int hash;  rem

                  volatile V value;     get

                  final HashEntry<K,V> next;  

            }

第一步是访问count变量,这是一个volatile变量,因为全部的修改操做在进行结构修改时都会在最后一步写count变量,经过这种机制保证get操做可以获得几乎最新的结构更新。对于非结构更新,也就是结点值的改变,因为HashEntry的value变量是volatile的,也能保证读取到最新的值。接下来就是对hash链进行遍历找到要获取的结点,若是没有找到,直接访回null。对hash链进行遍历不须要加锁的缘由在于链指针next是final的。可是头指针却不是final的,这是经过getFirst(hash)方法返回,也就是存在table数组中的值。这使得getFirst(hash)可能返回过期的头结点,例如,当执行get方法时,刚执行完getFirst(hash)以后,另外一个线程执行了删除操做并更新头结点,这就致使get方法中返回的头结点不是最新的。这是能够容许,经过对count变量的协调机制,get能读取到几乎最新的数据,虽然可能不是最新的。要获得最新的数据,只有采用彻底的同步。

2:删除操做remove

获取段锁,先定位到段,而后委托段去执行删除操做。当多个删除操做并行时,只要不是在同一个段,就能够同时进行。

3:put

该方法也是在持有锁的状况下执行的,首先判断是否须要rehash,须要就先rehash。接着是找是否存在一样一个key的结点,若是存在就直接替换这个结点的值。不然建立一个新的结点并添加到hash链的头部,这时必定要修改modCount和count的值,一样修改count的值必定要放在最后一步。put方法调用了rehash方法,reash方法实现得也很精巧,主要利用了table的大小为2^n,这里就不介绍了

相关文章
相关标签/搜索