前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java常用并发容器总结(二)

Java常用并发容器总结(二)

作者头像
张申傲
发布2020-09-03 10:30:00
2690
发布2020-09-03 10:30:00
举报
文章被收录于专栏:漫漫架构路

ConcurrentHashMap

1.介绍

ConcurrentHashMap是一个高效并发的HashMap,它采用了减小锁粒度的手段,内部进一步细分成了若干个小的HashMap,称为Segment段。默认情况下,一个ConcurrentHashMap被分为16个段。多ConcurrentHashMap操作时,并不是将整个ConcurrentHashMap加锁,而是首先根据hashCode定位到要操作的Segment,然后对该段进行加锁。在多线程环境下,如果多个线程操作同一个ConcurrentHashMap的不同Segment,可以做到真正的并行,大大提高了效率。

2.代码分析

下面以ConcurrentHashMap的put()方法为例,分析ConcurrentHashMap的操作策略:

代码语言:javascript
复制
public V put(K key, V value) {
        Segment<K,V> s;
        if (value == null)
            throw new NullPointerException();

        //计算key的hashCode
        int hash = hash(key);

        //根据hashCode,找到要进行操作的段
        int j = (hash >>> segmentShift) & segmentMask;
        if ((s = (Segment<K,V>)UNSAFE.getObject          
             (segments, (j << SSHIFT) + SBASE)) == null)
            s = ensureSegment(j);

        //对该段进行put
        return s.put(key, hash, value, false);
    }

可以看出,对ConcurrentHashMap的put操作,可以将粒度减小为对某一个Segment的操作,大大减小了锁的竞争,提高并发效率。 但是,减小锁的粒度引入了一个新的问题,当系统需要获得全局锁时,消耗的资源较多。以size()方法为例:

代码语言:javascript
复制
public int size() {       
        final Segment<K,V>[] segments = this.segments;
        int size;
        boolean overflow; 
        long sum;        
        long last = 0L;  
        int retries = -1; 
        try {
            for (;;) {
                if (retries++ == RETRIES_BEFORE_LOCK) {
                    for (int j = 0; j < segments.length; ++j)

                        //在这里,需要多每一个Segment分别加锁
                        ensureSegment(j).lock(); 
                }
                sum = 0L;
                size = 0;
                overflow = false;
                for (int j = 0; j < segments.length; ++j) {
                    Segment<K,V> seg = segmentAt(segments, j);
                    if (seg != null) {

                        //计算size总数
                        sum += seg.modCount;
                        int c = seg.count;
                        if (c < 0 || (size += c) < 0)
                            overflow = true;
                    }
                }
                if (sum == last)
                    break;
                last = sum;
            }
        } finally {
            if (retries > RETRIES_BEFORE_LOCK) {
                for (int j = 0; j < segments.length; ++j)

                    //这里再分别释放每一段的锁
                    segmentAt(segments, j).unlock();
            }
        }
        return overflow ? Integer.MAX_VALUE : size;
    }

可以看出,在高并发的场景下,ConcurrentHashMap的size()方法的效率要明显低于HashMap。

3.适用场景

简单地说,如果想在高并发的场景下使用HashMap,那么ConcurrentHashMap将是一个很好的选择。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017/03/31 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ConcurrentHashMap
  • 1.介绍
  • 2.代码分析
  • 3.适用场景
相关产品与服务
腾讯云代码分析
腾讯云代码分析(内部代号CodeDog)是集众多代码分析工具的云原生、分布式、高性能的代码综合分析跟踪管理平台,其主要功能是持续跟踪分析代码,观测项目代码质量,支撑团队传承代码文化。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档