栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

并发容器的选择

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

并发容器的选择

并发容器的选择
  • 结论
  • 为啥不用hashMap
  • Hashtable 和 concurrentHashMap 区别
    • Hashmap
    • HashTable

结论

为啥不用hashMap

请切记,并发环境下不要使用hashmap。原因是jdk1.7之前使用hashmap进行扩容时,会造成死循环。虽然在1.8修复了这个问题,但是高并发情况下依然会导致数据不准确的问题(查看hash源码会发现,没有使用锁,因此本质上hashmap就是线程不安全的)

Hashtable 和 concurrentHashMap 区别 Hashmap

我们先看下jdk1.8中concurrentHashMap 的实现

// An highlighted block
 public V put(K key, V value) {
        return putVal(key, value, false);
    }

    
    final V putVal(K key, V value, boolean onlyIfAbsent) {
     		//省略逻辑
            V oldVal = null;
                synchronized (f)
                }

           
public V remove(Object key) {
        return replaceNode(key, null, null);
    }

    
    final V replaceNode(Object key, V value, Object cv) {
 			//省略逻辑
                synchronized (f) 
                }

从源码可以看出concurrentHashMap中的remove(),clear(),put()方法都使用了锁,实现了细粒度的锁,减少了竞争锁的开销(可能产生锁竞争的地方减少了)。
但是!!!!
我们看下他的get方法,没有加锁。

// An highlighted block
    public V get(Object key) {
        Node[] tab; Node e, p; int n, eh; K ek;
        int h = spread(key.hashCode());
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (e = tabAt(tab, (n - 1) & h)) != null) {
            if ((eh = e.hash) == h) {
                if ((ek = e.key) == key || (ek != null && key.equals(ek)))
                    return e.val;
            }
            else if (eh < 0)
                return (p = e.find(h, key)) != null ? p.val : null;
            while ((e = e.next) != null) {
                if (e.hash == h &&
                    ((ek = e.key) == key || (ek != null && key.equals(ek))))
                    return e.val;
            }
        }
        return null;
    }

同理他的size方法也没有加锁.
这里可以看出容易产生读不一致的问题,即两次读可能结果不一样。因此,如果对读有较强的一致性要求则明显不适应

HashTable
   public synchronized V put(K key, V value) {
        // Make sure the value is not null
        if (value == null) {
            throw new NullPointerException();
        }

        // Makes sure the key is not already in the hashtable.
        Entry tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        @SuppressWarnings("unchecked")
        Entry entry = (Entry)tab[index];
        for(; entry != null ; entry = entry.next) {
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }

        addEntry(hash, key, value, index);
        return null;
    }

hashtable 中的put方法等都是这样简单粗暴的锁住整个方法,因此产生的锁竞争就更多了。但同时也保证了数据的强一致性。因此,如果对数据一致性要求高的话可以用hashtable,但是自然效率就没有concurrentHashMap高

好了,map的分享就到这里了。下期我再分享list的容器选择。
我是和弦,一名互联网枸杞人,如果文章对你有帮助,请点个赞吧!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/975924.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号