欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

HashMap与ConcurrentHashMap的区别

程序员文章站 2022-04-20 14:47:58
...

        从JDK1.2起,就有了HashMap,正如前一篇文章所说,HashMap不是线程安全的,因此多线程操作时需要格外小心。

        在JDK1.5中,伟大的Doug Lea给我们带来了concurrent包,从此Map也有安全的了。

HashMap与ConcurrentHashMap的区别
            
    
    博客分类: java基础 HashMapConcurrentHashMap 

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

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

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

    /**
     * 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方法:

HashMap与ConcurrentHashMap的区别
            
    
    博客分类: java基础 HashMapConcurrentHashMap 
        Segment.remove方法:

HashMap与ConcurrentHashMap的区别
            
    
    博客分类: java基础 HashMapConcurrentHashMap 

参考文章:http://blog.csdn.net/xuefeng0707/article/details/40834595

  • HashMap与ConcurrentHashMap的区别
            
    
    博客分类: java基础 HashMapConcurrentHashMap 
  • 大小: 21.2 KB
  • HashMap与ConcurrentHashMap的区别
            
    
    博客分类: java基础 HashMapConcurrentHashMap 
  • 大小: 35.3 KB
  • HashMap与ConcurrentHashMap的区别
            
    
    博客分类: java基础 HashMapConcurrentHashMap 
  • 大小: 22.9 KB