博客
关于我
ConcurrentHashMap了解吗?说说实现原理。
阅读量:610 次
发布时间:2019-03-12

本文共 1322 字,大约阅读时间需要 4 分钟。

HashMap 是线程不安全的,效率高;HashTable 是线程安全的,效率低。

ConcurrentHashMap 可以做到既是线程安全的,同时也可以有很高的效率,得益于使用了分段锁。

 

实现原理

JDK 1.7:

  • ConcurrentHashMap 是通过数组 + 链表实现,由 Segment 数组和 Segment 元素里对应多个 HashEntry 组成
  • value 和链表都是 volatile 修饰,保证可见性
  • ConcurrentHashMap 采用了分段锁技术,分段指的就是 Segment 数组,其中 Segment 继承于 ReentrantLock
  • 理论上 ConcurrentHashMap 支持 CurrencyLevel (Segment 数组数量)的线程并发,每当一个线程占用锁访问一个 Segment 时,不会影响到其他的 Segment

 

put 方法的逻辑较复杂:

  • 尝试加锁,加锁失败 scanAndLockForPut 方法自旋,超过 MAX_SCAN_RETRIES 次数,改为阻塞锁获取
  • 将当前 Segment 中的 table 通过 key 的 hashcode 定位到 HashEntry
  • 遍历该 HashEntry,如果不为空则判断传入的 key 和当前遍历的 key 是否相等,相等则覆盖旧的 value
  • 不为空则需要新建一个 HashEntry 并加入到 Segment 中,同时会先判断是否需要扩容
  • 最后释放所获取当前 Segment 的锁

 

get 方法较简单:

  • 将 key 通过 hash 之后定位到具体的 Segment,再通过一次 hash 定位到具体的元素上
  • 由于 HashEntry 中的 value 属性是用 volatile 关键词修饰的,保证了其内存可见性

 

JDK 1.8:

  • 抛弃了原有的 Segment 分段锁,采用了 CAS + synchronized 来保证并发安全性
  • HashEntry 改为 Node,作用相同
  • val next 都用了 volatile 修饰

 

put 方法逻辑:

  • 根据 key 计算出 hash 值
  • 判断是否需要进行初始化
  • 根据 key 定位出的 Node,如果为空表示当前位置可以写入数据,利用 CAS 尝试写入,失败则自旋
  • 如果当前位置的 hashcode == MOVED == -1,则需要扩容
  • 如果都不满足,则利用 synchronized 锁写入数据
  • 如果数量大于 TREEIFY_THRESHOLD 则转换为红黑树

 

get 方法逻辑:

  • 根据计算出来的 hash 值寻址,如果在桶上直接返回值
  • 如果是红黑树,按照树的方式获取值
  • 如果是链表,按链表的方式遍历获取值

 

JDK 1.7 到 JDK 1.8 中的 ConcurrentHashMap 最大的改动:

  • 链表上的 Node 超过 8 个改为红黑树,查询复杂度 O(logn)
  • ReentrantLock 显示锁改为 synchronized,说明 JDK 1.8 中 synchronized 锁性能赶上或超过 ReentrantLock

 

参考:

 

 


【Java面试题与答案】整理推荐

 

转载地址:http://elaxz.baihongyu.com/

你可能感兴趣的文章
mysql id自动增长 初始值 Mysql重置auto_increment初始值
查看>>
MySQL in 太多过慢的 3 种解决方案
查看>>
MySQL InnoDB 三大文件日志,看完秒懂
查看>>
Mysql InnoDB 数据更新导致锁表
查看>>
Mysql Innodb 锁机制
查看>>
MySQL InnoDB中意向锁的作用及原理探
查看>>
MySQL InnoDB事务隔离级别与锁机制深入解析
查看>>
Mysql InnoDB存储引擎 —— 数据页
查看>>
Mysql InnoDB存储引擎中的checkpoint技术
查看>>
Mysql InnoDB存储引擎中缓冲池Buffer Pool、Redo Log、Bin Log、Undo Log、Channge Buffer
查看>>
MySQL InnoDB引擎的锁机制详解
查看>>
Mysql INNODB引擎行锁的3种算法 Record Lock Next-Key Lock Grap Lock
查看>>
mysql InnoDB数据存储引擎 的B+树索引原理
查看>>
mysql innodb通过使用mvcc来实现可重复读
查看>>
mysql insert update 同时执行_MySQL进阶三板斧(三)看清“触发器 (Trigger)”的真实面目...
查看>>
mysql interval显示条件值_MySQL INTERVAL关键字可以使用哪些不同的单位值?
查看>>
Mysql join原理
查看>>
MySQL Join算法与调优白皮书(二)
查看>>
Mysql order by与limit混用陷阱
查看>>
Mysql order by与limit混用陷阱
查看>>