学习笔记(20):Java面试Offer直通车-用ConcurrentHashmap综合展示并发、集合和读源码的能力

立即学习:https://edu.csdn.net/course/play/27126/357994?utm_source=blogtoedu

对比jdk1.7和1.8的差别,介绍ConcurrentHashMap 和HashMap 和SynchronizedMap 的差别

  1. HashMap 线程不安全
  2. jdk1.7以“锁”segment的方式保证并发
  3. JDK1.8里,以“CAS”的方式保证并发
  4. SynchronizedMap的put和get封装了HashMap 相关方法,并通过互斥锁保证线程安全
  5. ConcurrentHashMap 做put时,用CAS+Synchronized保证线程安全,更轻量

jdk1.7的实现方式

  1. segment数组-HashEtry数组-HashEntry列表
  2. 读时不加锁,写时加锁segment
  3. 两次hash,一次定位到segment,一次定位到HashEntry头部

jdk1.8的实现方式

  1. 以node数组加列表或红黑树的方式实现
  2. 冲突 会产生链表,链表数大于8,以红黑树方式存储
  3. 遍历链表时间复杂度是O(n),遍历红黑树时Of(logN),利于冲突数大的场景

jdk1.8里put的实现细节

  1.    如果Node数组为空,则调用initTable方法初始化Node数组
  2. 计算key的hash值,并定位到Node里的对应位置
  3. 如果当前Node位置为空,即无冲突,则以CAS方式插入
  4. 多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。

通过put和get源码,了解ConcurrentHashMap 的底层结构和hash流程

以CAS+Synchronized管理并发的方式

CAS的讲解

  1. Compare And Swap, CAS (V,E,N) 如V等于E,则将V设为N,若V和E不等,说明已有其他线程做了更新,当前线程什么都不做,或更改V、E和N参数再重试
  2. put里的casTabAt方法,实际调用compareAndSwapObject
  3. 比较当前tab里的i号索引是否为null,是则插入Node<k,v>,不是则说明有其他线程已更改,不做操作

jdk1.8里put的实现细节

  1. 如果当前Node不为空,对该Node加synchronized锁,并加入到该Node锁指向的链表里
  2. 如当前Node包含链表节点数大于8,则用treeifyBin方法把链表转红黑树
  3. 如当前Node已经用红黑树存储数据,则通过putTreeVal 方法插入新的键值对

JDK1.8里get方法的实现细节

  1. 计算key的hash值,如果Node数组里匹配到首结点即返回
  2. 否则调用next方法遍历链表或红黑树,由于可能会有冲突,需调用equals

 

以实例介绍volatile的含义

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值