博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从volatile解读ConcurrentHashMap(jdk1.6.0)无锁读
阅读量:6240 次
发布时间:2019-06-22

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

作者:绫萱

volatile常常用于修饰多线程共享变量,用来保证该变量的可见性。volatile的语意:某个写线程对volatile变量的写入马上可以被后续的某个读线程“看”到。

volatile保证可见性的原理:volatile是通过在编译器生成字节码时,在对volatile变量进行读写指令序列的前后加入内存屏障,来禁止一些处理器重排序保证写入一定发生在读之前的这种happen-before关系。

 

简单理解:在本次线程内,当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个线程本地内存中;以后再取变量值时,就直接从本地内存中取值;当变量值在本线程里改变时,会同时把变量的新值copy到本地内存中,以便保持一致;在某个特定的时候,将本地内存的更改写到系统主内存中去;当变量在因别的线程等而改变了值,并且该变化没有写到系统主内存,本次线程的本地内存中的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致;但是当变量被volatile修饰后,每次更改该变量的时候会将更改结果写到系统主内存中,利用多处理器的缓存一致性,其他处理器会发现自己的缓存行对应的内存地址被修改,就会将自己处理器的缓存行设置为失效,并强制从系统主内存获取最新的数据。这样就能保证即使在别的线程中改变了该变量的值,在本线程中也能取到最新更改后的值。 ConcurrentHashMap之所以有较好的并发性是因为ConcurrentHashMap是无锁读和加锁写,并且利用了分段锁(不是在所有的entry上加锁,而是在一部分entry上加锁)。

那ConcurrentHashMap是怎么实现无锁读的呢?

 
这是在jdk1.6.0中的读的实现。

不得不赞叹,作者深厚的功底啊,当执行读的时候,先判断count,count就是一个Segment(充当锁的角色)所守护HashEntry的数量。
 

这里的count是被volatile修饰的。当对这段表的结构进行更改时,在退出前都会去更改count。由于volatile的语意:某个写线程对volatile变量的写入马上可以被后续的某个读线程“看”到,所以这里对count的读一定发生在对count写之后,获得是最新的count。在无锁读的方法中,首先去读取这个最近的count,保证了在执行无锁读的时候表的结构没有被改变。(利用了volatile变量写读的happen-before关系)。   同时当把value设置为volatile时,其他线程所做的改变就能马上被当前线程感知。这样就能支持多个线程并发读了~   不过我们也知道volatile并不能保证线程安全,它是轻量级的synchronized。   要使 volatile变量提供理想的线程安全,必须同时满足下面两个条件:              ● 对变量的写操作不依赖于当前值。              ● 该变量没有包含在具有其他变量的不变式中。举例:线程安全计数器的自增操作,其实是由3个操作读取-修改-写入操作序列组成的组合操作,volatile不能保证原子性,不能保证在操作期间该变量的值不会改变。   其实这是一种常见的volatile的利用场景——开销较低的读-写锁策略。如果读操作远远超过写操作,您可以结合使用内部锁和 volatile变量来减少公共代码路径的开销。这样读操作只是volatile读操作,性能优于一个无竞争的锁获取的开销。但是当需要对该变量执行写操作,应该加锁。  PS:这里ConcurrentHashMap也有加锁读的情况。利用方法  V readValueUnderLock(HashEntry
e)。只有value为空的时候,才会加锁读,这种情况就是编译器对value的赋值操作进行重排序了。 感谢家纯师兄的订正和指导。

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

你可能感兴趣的文章
New Concept English Two 18 46
查看>>
Qt 删除目录
查看>>
Git 移除某些文件
查看>>
poj2940
查看>>
django做form表单的数据验证
查看>>
【OpenFOAM】——OpenFOAM入门算例学习
查看>>
STL UVA 11991 Easy Problem from Rujia Liu?
查看>>
模拟 URAL 1149 Sinus Dances
查看>>
Oracle 11G 数据库迁移【expdp/impdp】
查看>>
17.EXTJs 中icon 与iconCls的区别及用法!
查看>>
3.mybatis实战教程(mybatis in action)之三:实现数据的增删改查
查看>>
Caused by: Unable to load bean: type: class:com.opensymphony.xwork2.ObjectFactory - bean - jar
查看>>
让你拥有超能力:程序员应该掌握的统计学公式
查看>>
互联网组织的未来:剖析 GitHub 员工的任性之源
查看>>
Java 开源博客 Solo 1.4.0 发布 - 简化
查看>>
Oracle巡检
查看>>
【转载】胜者树
查看>>
查看mysql数据库存放的路径|Linux下查看MySQL的安装路径
查看>>
selenium+testNG+Ant
查看>>
1024程序员节,你屯书了吗?(内含福利)
查看>>