zoukankan      html  css  js  c++  java
  • Java HashMap

    HashMap:先说HashMap,HashMap是线程不安全的,在并发环境下,可能会形成环状链表(扩容时可能造成,具体原因自行百度google或查看源码分析),
    导致get操作时,cpu空转,所以,在并发环境中使用HashMap是非常危险的.

    HashTable:HashTable和HashMap的实现原理几乎一样,差别无非是1.HashTable不允许key和value为null;2.HashTable是线程安全的
    但是HashTable线程安全的策略实现代价却太大了,简单粗暴,get/put所有相关操作都是synchronized的,
    这相当于给整个哈希表加了一把[大锁],多线程访问时候,只要有一个线程访问或操作该对象,那其他线程只能阻塞,相当于将所有的操作串行化,在竞争激烈的并发场景中性能就会非常差。
    HashTable[全表锁机制]--性能较差

    ConcurrentHashMap采用了非常精妙的"分段锁"策略,ConcurrentHashMap的主干是个Segment数组.
    Segment继承了ReentrantLock,所以它就是一种可重入锁(ReentrantLock)。
    在ConcurrentHashMap,一个Segment就是一个子哈希表,Segment里维护了一个HashEntry数组,并发环境下,
    对于不同Segment的数据进行操作是不用考虑锁竞争的。(按默认的ConcurrentLeve为16来讲,理论上就允许16个线程并发执行)


    put的过程很清晰,对当前的table进行无条件自循环直到put成功,可以分成以下六步流程来概述
    1.如果没有初始化就先调用initTable()方法来进行初始化过程
    2.如果没有hash冲突就直接CAS插入
    3.如果还在进行扩容操作就先进行扩容
    4.如果存在hash冲突,就加锁来保证线程安全,这里有两种情况,一种是链表形式就直接遍历到尾端插入,一种是红黑树就按照红黑树结构插入,
    5.最后一个如果该链表的数量大于阈值8,就要先转换成黑红树的结构,break再一次进入循环
    6.如果添加成功就调用addCount()方法统计size,并且检查是否需要扩容


    ConcurrentHashMap的get操作的流程很简单,也很清晰,可以分为三个步骤来描述
    1.计算hash值,定位到该table索引位置,如果是首节点符合就返回
    2.如果遇到扩容的时候,会调用标志正在扩容节点ForwardingNode的find方法,查找该节点,匹配就返回
    3.以上都不符合的话,就往下遍历节点,匹配就返回,否则最后就返回null

  • 相关阅读:
    ADO.NET连接方式
    ffmpeg架构和解码流程分析
    [置顶] 纠正下关于机器学习实战书中51页代码的错误
    hadoop-1.1.2 在Windows环境下的部署
    hive load from hdfs出错
    金额查错:某财务部门结账时发现总金额不对头。很可能是从明细上漏掉了某1笔或几笔, 如果已知明细账目清单,能通过编程找到漏掉的是哪1笔或几笔吗?
    android下获取无线wif信号、ssid、MAC等操作类
    [置顶] ios 一个不错的图片浏览分享框架demo
    Linux 获取设备树源文件(DTS)里描述的资源
    使用Httpwatch分析响应时间--转
  • 原文地址:https://www.cnblogs.com/jasonandy/p/9821555.html
Copyright © 2011-2022 走看看