前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ConcurrentHashMap源码解读[面试专题](集合相关)

ConcurrentHashMap源码解读[面试专题](集合相关)

作者头像
高大北
发布2022-06-14 20:49:51
1870
发布2022-06-14 20:49:51
举报
文章被收录于专栏:java架构计划训练营

JDK1.7ConcurrentHashMap源码解读

使用传统HashTable保证线程问题,是采用synchronized锁将整个HashTable中的数组锁住, 在多个线程中只允许一个线程访问Put或者Get,效率非常低,但是能够保证线程安全问题。

Jdk官方不推荐在多线程的情况下使用HashTable或者HashMap,建议使用ConcurrentHashMap分段HashMap。 效率非常高。

ConcurrentHashMap将一个大的HashMap集合拆分成n多个不同的小的HashTable(Segment),默认的情况下是分成16个不同的 Segment。每个Segment中都有自己独立的HashEntry<K,V>[] table;

核心参数:

initialCapacity —16 初始化

loadFactor HashEntry<K,V>[] table; 加载因子0.75

concurrencyLevel 并发级别 默认是16

cas与乐观锁机制原理(简单)

一直卡死,消耗cpu资源,一直重试。

hashtable缺点

底层使用synchronized锁实现的,但是将整个数组都给锁住了。

1.7ConcurrentHashMap

将一个大的ConcurrentHashMap集合拆分成n多个不同的hashtable,在每个小的hashtable中都有自己的table【】

代码语言:javascript
复制
package com.gtf.xc;

import java.util.HashMap;

public class MyConcurrentHashMap
        <K, V> {
    /**
     * segments
     */
    private HashMap<K,V>[] segments;
    public MyConcurrentHashMap() {
        segments=new HashMap[16];
        //注意是懒加载
    }
    public void put(K key, V value) {
        //第一次计算key,计算key存放在哪一个hashtable
        int segmentsIndex =key.hashCode()& (segments.length  - 1);
        HashMap<K, V> segment = segments[segmentsIndex];
        //segment == null
        if (segment == null) {
            segment=new HashMap<>();
        }
        segment.put(key,value);
        segments[segmentsIndex]=segment;
    }
    public V get(K key) {
        int segmentsIndex =key.hashCode()& (segments.length  - 1);
        HashMap<K, V> segment = segments[segmentsIndex];
        if (segment != null) {
          return  segment.get(key);
        }
        return null;
    }

    public static void main(String[] args) {
        MyConcurrentHashMap<Object, Object> objectObjectMyConcurrentHashMap = new MyConcurrentHashMap<>();
        for (int i = 0; i < 10; i++){
            objectObjectMyConcurrentHashMap.put(i,i);
        }
       for (int i = 0; i < 10; i++) {
           objectObjectMyConcurrentHashMap.get(i);
           System.out.println( objectObjectMyConcurrentHashMap.get(i));
       }

    }
}

没有获取到锁的线程

  1. 自旋 缓存当前对应冲突链表
  2. 每次检查 当前缓存链表头节点是否发生变化
  3. 如果发生变化的情况下 缓存最新
  4. 自旋的次数最多为64

实现原理

  • 由多个不同的sement对象组成
  • 使用 luck锁+cas
  • unsafe 直接查询主内存最新的数据
  • 使用cas做修改

JDK1.8ConcurrentHashMap

ConcurrentHashMap1.8的取出取消segment分段设计,采用对CAS + synchronized保证并发线程安全问题,将锁的粒度拆分到每个index 下标位置,实现的效率与ConcurrentHashMap1.7相同。

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JDK1.7ConcurrentHashMap源码解读
  • 核心参数:
    • initialCapacity —16 初始化
      • loadFactor HashEntry<K,V>[] table; 加载因子0.75
        • concurrencyLevel 并发级别 默认是16
        • cas与乐观锁机制原理(简单)
        • hashtable缺点
        • 1.7ConcurrentHashMap
          • 没有获取到锁的线程
            • 实现原理
            • JDK1.8ConcurrentHashMap
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档