HashMap 和ConcurrentHashMap 原理介绍

HashMap原理介绍

Java 位运算说明

ConcurrentHashMap 分析

  • ConcurrentHashMap 在jdk 1.7 和jdk 1.8 中 的实现有很大不同.(参考1参考2
    jdk 1.8 的改进:

    1. 取消segments字段,直接采用transient volatile HashEntry<K,V>[] table保存数据,采用table数组元素作为锁,从而实现了对每一行数据进行加锁,进一步减少并发冲突的概率。
    2. 将原先table数组+单向链表的数据结构,变更为table数组+单向链表+红黑树的结构。对于hash表来说,最核心的能力在于将key hash之后能均匀的分布在数组中。如果hash之后散列的很均匀,那么table数组中的每个队列长度主要为0或者1。但实际情况并非总是如此理想,虽然ConcurrentHashMap类默认的加载因子为0.75,但是在数据量过大或者运气不佳的情况下,还是会存在一些队列长度过长的情况,如果还是采用单向列表方式,那么查询某个节点的时间复杂度为O(n);因此,对于个数超过8(默认值)的列表,jdk1.8中采用了红黑树的结构,那么查询的时间复杂度可以降低到O(logN),可以改进性能。将原先table数组+单向链表的数据结构,变更为table数组+单向链表+红黑树的结构。对于hash表来说,最核心的能力在于将key hash之后能均匀的分布在数组中。如果hash之后散列的很均匀,那么table数组中的每个队列长度主要为0或者1。但实际情况并非总是如此理想,虽然ConcurrentHashMap类默认的加载因子为0.75,但是在数据量过大或者运气不佳的情况下,还是会存在一些队列长度过长的情况,如果还是采用单向列表方式,那么查询某个节点的时间复杂度为O(n);因此,对于个数超过8(默认值)的列表,jdk1.8中采用了红黑树的结构,那么查询的时间复杂度可以降低到O(logN),可以改进性能。
  • ConcurrentHashMap 如何做到线程安全
    很多文章说 ConcurrentHashMap 是用的分段锁技术 来 实现高并发, 这是jdk1.7 中的实现, jdk1.8 中 使用的是 synchronized 每个 table 的node 对象来实现减少了锁的粒度。 在jdk 1.8 中 synchronized 进行了优化,效率和ReentrantLock 差不多。

  • ConcurrentHashMap 弱一致性的问题:
    ConcurrentHashMap 有很多操作,get ,put, iterator…, 这里来分析下这些方法的一致性

    1. ConcurrentHashMap #get 早期 ConcurrentHashMap 存在弱一致性问题,主要是因为 put 操作 中 table 加了 volatile,但table中的元素不是volatile的,同时 get 操作没有 加锁。会出现写入的数据不是立刻可见,jdk 1.8 中 通过
 pred.next = new Node<K,V>(hash, key,value, null);

来添加元素,put 的元素能立刻可见,不再是弱一致性
详细分析1详细分析2
2. ConcurrentHashMap #iterator 在并发时,线程增加的字段不是立刻可见的。还是弱一致性, 这里不能打印出6666 详细分析1

    public static void main(String[] str){
        //ConcurrentHashMap<String, String> testCHM = new ConcurrentHashMap<String, String>();  //一个线程在读concurrentHashMap, 另外一个线程在写concurrentHashMap,
        //遍历的过程中写入没法读到当前的值.
        HashMap<String, String> testCHM = new HashMap<String, String>();  //HashMap 中一个线程读,一个线程写会抛出异常ConcurrentModificationException
        testCHM.put("1","11111");
        testCHM.put("2","22222");
        testCHM.put("3","33333");
        testCHM.put("4","44444");
        testCHM.put("5","55555");
        testCHM.put("7","77777");
        testCHM.put("8","88888");

        new Thread(new Runnable() {
            @Override
            public void run(){
                try {
                    Thread.sleep(6000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("------开始插入66666-------");
                testCHM.put("6","66666");
                System.out.println("----------结束插入666-----");

            }
        }).start();
       for(Map.Entry entry: testCHM.entrySet()){
            System.out.println(entry.getValue());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
  • ConcurrentHashMap 能否完全取代HashTable?:
    ConcurrentHashMap 的iterator是弱一致性,而HashTable 是强一致性。并不能完全替换。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值