搜文章
推荐 原创 视频 Java开发 iOS开发 前端开发 JavaScript开发 Android开发 PHP开发 数据库 开发工具 Python开发 Kotlin开发 Ruby开发 .NET开发 服务器运维 开放平台 架构师 大数据 云计算 人工智能 开发语言 其它开发
Lambda在线 > 技术修养之路 > Java中Map线程安全实现

Java中Map线程安全实现

技术修养之路 2019-02-11

  • 前言介绍:volatile和transient关键字

  • 第一种实现:HashTable

  • 第二种实现:Collections.synchronizedMap(map)

  • 第三种实现:ConcurrentHashMap

前言介绍:volatile和transient关键字

volatile(易变的,不稳定的),作用:

  1. volatile变量写入时:JVM会把该线程对应的本地内存私有拷贝变化强制刷新到主内存中去, 并且会其他线程中的本地内存私有拷贝无效;

  2. volatile变量读取时:强迫从主内存中重读该成员变量的值;JVM为了获得最佳速度,允许每个线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才与共享成员变量的原始值对比(如下图)。volatile关键字就是告诉JVM,不要优化了,我是易变的,是在多线程中访问的成员变量,如果是synchronized代码块中变量,或者最终常量,那么就不需要volatileJava中Map线程安全实现

  3. 根据1,2两点特性,volatile变量控制多个线程读写,同时操作主存,是不是绝对线程安全了呐?答案是NO,可以肯定如果是 volatile int count = 1; 在多个线程中操作count = 2;这种原子操作是线程安全的;相反:一些读写复合操作 count++,会先读取count,然后加一,最后赋值count。只依靠volatile就不行了,AtomicInteger是采用CAS(compare and swap)机制,实现无锁线程安全。

  4. 禁止指令重排序优化

    首先指令重排序优化是什么?

    重排序是对代码指令的执行顺序重拍:比如说,a=1;b=3;,JVM可能会重排序为先b=3;a=1;如果fun和run并发执行,最终b可能是2或者3

Java中Map线程安全实现

transient(短暂的,临时的),作用:

先说说Serializable接口是赋予对象可序列化和反序列化的。transient修饰的变量,序列化到文件中对应的值为NOT SET

第一种实现:HashTable

核心思想synchronized修饰所有方法体

从put方法可以看出,不允许key,value为空

Java中Map线程安全实现

Java中Map线程安全实现

第二种实现:Collections.synchronizedMap(map)

源码发现,核心点在于final Map m;是一个指针指向传入的map参数,并且这个指针是不可改变的,如果后续令map = null;并不影响这个final变量的指向;Object mutex(互斥体)使用synchronized获取这个互斥体变量的占有,确保了多线程安全

Java中Map线程安全实现

下图注释1操作是把map1指针指向的Map对象清空,syncmap1指向的Map对象也清空了,所以去除是null;注释1操作是把map2指针清空,并不影响syncmap2已经记录了指向的Map对象

Java中Map线程安全实现

    第一种和第二种实现在put和get会争夺锁,如果大量读取和写入并不在同一段?那么就引出了第三种实现

第三种实现:ConcurrentHashMap

    JDK7容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并发访问效率,这就是ConcurrentHashMap所使用的锁分段技术,首先将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。有些方法需要跨段,比如size()和containsValue(),它们可能需要锁定整个表而而不仅仅是某个段,这需要按顺序锁定所有段,操作完毕后,又按顺序释放所有段的锁。这里“按顺序”是很重要的,否则极有可能出现死锁

Java中Map线程安全实现

    JDK8实现已经摒弃了Segment的概念,而是直接用Node数组+链表+红黑树的数据结构来实现,并发控制使用synchronized和CAS来操作,整个看起来就像是优化过且线程安全的HashMap

    因为锁力度降低到单个node,所以使用synchronized来控制锁,synchronized关键字也是官方一直在JVM底层持续优化,效率更高

Java中Map线程安全实现

    val和next都会在扩容时发生变化,所以加上volatile来保持可见性和禁止重排序

Java中Map线程安全实现

Java中Map线程安全实现

    弱化后的Segment:


版权声明:本站内容全部来自于腾讯微信公众号,属第三方自助推荐收录。《Java中Map线程安全实现》的版权归原作者「技术修养之路」所有,文章言论观点不代表Lambda在线的观点, Lambda在线不承担任何法律责任。如需删除可联系QQ:516101458

文章来源: 阅读原文

相关阅读

关注技术修养之路微信公众号

技术修养之路微信公众号:TechPersonCulture

技术修养之路

手机扫描上方二维码即可关注技术修养之路微信公众号

技术修养之路最新文章

精品公众号随机推荐