java8同步容器类ConcurrentHashMap类介绍

从JDK1.2起,就有了HashMap,正如前一篇文章所说,HashMap不是线程安全的,因此多线程操作时需要格外小心。ConcurrentHashMap同步容器类是java5增加的一个线程安全的哈希表,对于多线程的操作,介于HashMap与Hashtable之间,内部采用“锁分段”机制。JDK1.8使用CAS算法实现多线程安全。

 

 ConcurrentHashMap具体是怎么实现线程安全的呢,肯定不可能是每个方法加synchronized,那样就变成了HashTable。

        从ConcurrentHashMap代码中可以看出,它引入了一个“分段锁”的概念,具体可以理解为把一个大的Map拆分成N个小的HashTable,根据key.hashCode()来决定把key放到哪个HashTable中。

        在ConcurrentHashMap中,就是把Map分成了N个Segment,put和get的时候,都是现根据key.hashCode()算出放到哪个Segment中:

Java代码  :

/** 
 * Maps the specified key to the specified value in this table. 
 * Neither the key nor the value can be null. 
 * 
 * <p> The value can be retrieved by calling the <tt>get</tt> method 
 * with a key that is equal to the original key. 
 * 
 * @param key key with which the specified value is to be associated 
 * @param value value to be associated with the specified key 
 * @return the previous value associated with <tt>key</tt>, or 
 *         <tt>null</tt> if there was no mapping for <tt>key</tt> 
 * @throws NullPointerException if the specified key or value is null 
 */  
@SuppressWarnings("unchecked")  
public V put(K key, V value) {  
    Segment<K,V> s;  
    if (value == null)  
        throw new NullPointerException();  
    int hash = hash(key);  
    int j = (hash >>> segmentShift) & segmentMask;  
    if ((s = (Segment<K,V>)UNSAFE.getObject          // nonvolatile; recheck  
         (segments, (j << SSHIFT) + SBASE)) == null) //  in ensureSegment  
        s = ensureSegment(j);  
    return s.put(key, hash, value, false);  
}  
/** 
 * Returns the value to which the specified key is mapped, 
 * or {@code null} if this map contains no mapping for the key. 
 * 
 * <p>More formally, if this map contains a mapping from a key 
 * {@code k} to a value {@code v} such that {@code key.equals(k)}, 
 * then this method returns {@code v}; otherwise it returns 
 * {@code null}.  (There can be at most one such mapping.) 
 * 
 * @throws NullPointerException if the specified key is null 
 */  
public V get(Object key) {  
    Segment<K,V> s; // manually integrate access methods to reduce overhead  
    HashEntry<K,V>[] tab;  
    int h = hash(key);  
    long u = (((h >>> segmentShift) & segmentMask) << SSHIFT) + SBASE;  
    if ((s = (Segment<K,V>)UNSAFE.getObjectVolatile(segments, u)) != null &&  
        (tab = s.table) != null) {  
        for (HashEntry<K,V> e = (HashEntry<K,V>) UNSAFE.getObjectVolatile  
                 (tab, ((long)(((tab.length - 1) & h)) << TSHIFT) + TBASE);  
             e != null; e = e.next) {  
            K k;  
            if ((k = e.key) == key || (e.hash == h && key.equals(k)))  
                return e.value;  
        }  
    }  
    return null;  
}  

        如果key.hashCode()相同,表示它们将会放在同一个Segment上,如果是并发放入的话,可能会阻塞直到前面的put动作完成。

        Segment.put方法:

  Segment.remove方法:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值