码迷,mamicode.com
首页 > 其他好文 > 详细

ConcurrentHashMap

时间:2015-06-28 12:36:36      阅读:124      评论:0      收藏:0      [点我收藏+]

标签:

  HashMap中未进行同步考虑,而Hashtable在每个方法上加上了synchronized,锁住了整个Hash表,一个时刻只能有一个线程操作,其他的线程则只能等待,在并发的环境下,这样的操作导致Hashtable的效率低下。

  Collections的静态方法synchronizedMap(HashMap hm)返回的是一个SynchronizedMap对象,SynchronizedMap也是对原HashMap中的方法加上synchronized,锁的粒度应该减小。

  ConcurrentHashMap将原来的原来的Hash表分成了16个桶(默认值),桶内的读操作是不加锁的,桶内的写操作是加上了锁的。这样的实现允许更多的线程同时地操作Hash表,在并发的环境下,应该选择的是ConcurrentHashMap。

  技术分享

  ConcurrentHashMap的get读操作中基本没有用到锁,可以看下面的代码:

 V get(Object key, int hash) {
            if (count != 0) { // read-volatile
                HashEntry<K,V> e = getFirst(hash);
                while (e != null) {
                    if (e.hash == hash && key.equals(e.key)) {
                        V v = e.value;
                        if (v != null)
                            return v;
                        return readValueUnderLock(e); // recheck
                    }
                    e = e.next;
                }
            }
            return null;
        }

  当读到的value是null时,处理是return readValueUnderLock(e);,因为整个的操作未加锁,上面的if (v != null)为false时,可能同时有其他线程修改了value的值,这里有进行一次同步的取值,如下:

V readValueUnderLock(HashEntry<K,V> e) {
            lock();
            try {
                return e.value;
            } finally {
                unlock();
            }
        }

  size读操作为了确保读的数据是准确的也进行了部分的加锁操作。

  写后读或者读后写都会造成数据的不一致,即使用线程安全类,应该做好对象的加锁。

 

  ConcurrentHashMap的写操作锁住了Segment 

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);
    }

  下面是针对Segment的写操作:

V put(K key, int hash, V value, boolean onlyIfAbsent) {
            lock();
            try {
                int c = count;
                if (c++ > threshold) // ensure capacity
                    rehash();
                HashEntry<K,V>[] tab = table;
                int index = hash & (tab.length - 1);
                HashEntry<K,V> first = tab[index];
                HashEntry<K,V> e = first;
                while (e != null && (e.hash != hash || !key.equals(e.key)))
                    e = e.next;

                V oldValue;
                if (e != null) {
                    oldValue = e.value;
                    if (!onlyIfAbsent)
                        e.value = value;
                }
                else {
                    oldValue = null;
                    ++modCount;
                    tab[index] = new HashEntry<K,V>(key, hash, first, value);
                    count = c; // write-volatile
                }
                return oldValue;
            } finally {
                unlock();
            }
        }

 

ConcurrentHashMap

标签:

原文地址:http://www.cnblogs.com/lnlvinso/p/4605307.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!