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替代。
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容