侧边栏壁纸
博主头像
高大北博主等级

所有的再见中,我最喜欢明天见

  • 累计撰写 208 篇文章
  • 累计创建 151 个标签
  • 累计收到 20 条评论
标签搜索

目 录CONTENT

文章目录

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

高大北
2022-06-01 / 0 评论 / 1 点赞 / 285 阅读 / 617 字 / 正在检测是否收录...

JDK1.7ConcurrentHashMap源码解读

使用传统HashTable保证线程问题,是采用synchronized锁将整个HashTable中的数组锁住,
在多个线程中只允许一个线程访问Put或者Get,效率非常低,但是能够保证线程安全问题。
1654046564262
Jdk官方不推荐在多线程的情况下使用HashTable或者HashMap,建议使用ConcurrentHashMap分段HashMap。
效率非常高。
1654046632395
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【】

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相同。
1654336101889

1

评论区