ConcurrentHashMap并发总结

  • ConcurrentHashMap(以下称为CHM)各版本

    • JDK 5:分段锁,必要时加锁。

      通过Segment来分段,减少每次操作map时都需要执行同步操作而必须阻塞从而无法继续执行的可能。

    • JDK 6:优化二次Hash算法。

      JDK 5中小整数的Hash高位不均匀分布,始终为高位15,JDK 6经优化后高低位保持均匀分布。

    • JDK 7 :Segment懒加载,volatile和cas。

      JDK 7 之前Segment随CHM初始化 ,JDK 7 实现了懒加载,使用时再初始化,又由于多线程时其他线程可能访问不到刚初始化的Segment,故在JDK7大量使用volatile。

    • JDK 8 :放弃Segment,基于HashMap原理的并发实现。

      内部直接访问table[],针对table[]里对应的Node加锁,新来的元素会放置于此Node后面。

  • CHM计数

    • JDK 5~7:基于Segment元素个数求和,二次不同就加锁再求一次。
    • JDK 8:引入CounterCell,本质上也是分段计数。
  • CHM是弱一致性

    • 添加元素后不一定马上能读到。
    • 清空后可能仍然有元素。
    • 遍历之前的段元素变化会读到。
    • 遍历后的段元素变化读不到。
    • 遍历时元素变化不抛异常。
  • CHM与HashTable对比

    锁类型 CHM HashTable
    大锁 对HashTable对象加锁
    小锁 JDK 5~7:分段锁,JDK 8:节点锁
    长锁 直接对方法加锁
    短锁 先尝试获取,失败再加锁
    读写锁共用 只有一把锁,从头锁到尾
    读写锁分离 JDK 5~7:读失败再加锁,JDK 8:voltile读,CAS写
  • 锁优化总结

    • 长锁不如短锁:尽可能只锁必要部分。
    • 大锁不如小锁:尽可能拆分加锁对象。
    • 公锁不如私锁:尽可能私有锁内逻辑。
    • 嵌套不如扁平:尽可能避免锁锁嵌套。
    • 分离读和写锁:尽可能分离读和写锁。
    • 粗化高频次锁:尽可能合并高频小锁。
    • 消除无用废锁:尽可能用volatile替代。

你可能感兴趣的:(ConcurrentHashMap并发总结)