java volatile是如何保证可见性的?
lock前缀指令干的事。
volatile 修饰的变量在进行写操作时会多出一条如下的汇编指令:
lock addl $0x0,(%esp)
volatile就是靠这个lock前缀指令去实现可见性的,当对volatile修饰的共享变量进行写操作时,lock前缀的指令在多核处理器下会引发两件事情:
1.将当前处理器缓存行的数据写回到系统内存。
为了提高处理的响应速度,处理器不直接和内存进行通信,而是先将系统内存的数据读到内部缓存中(L1,L2或其他)在进行操作,但是操作完不知道会何时写入到内存中。如果对volatile修饰的变量进行写操作,JVM就会向处理器发送一条Lock前缀的指令,处理器收到指令都就会立即将缓存行的数据写入到内存中。需要注意的是Lock前缀指令导致在执行指令期间,声言处理的LOCK#信号。在多处理器环境中,LOCK#信号确保在声言信号期间,处理器可以独占任何共享缓存,会使用总线锁(锁住总线,导致其他cpu不能访问总线,总线系统连接者cpu和内存,总线一旦不能访问就意味着其他cpu无法访问内存),但是在最近的处理器中,LOCK#信号一般不锁总线(注意是一般,特殊情况下还是会锁总线,比如数据跨多个缓存行),而是锁缓存,毕竟锁总线开销比较大。对于Intel486和Pentium处理器,在锁操作期间,总是在总线上声言LOCK#信号。但在目前的处理器中,如果访问的内存已经缓存在处理器内部,则不会声言LOCK#信号。相反,他会锁定这块内存区域的缓存并回写到内存,并使用缓存一致性机制来确保修改的原子性,这种操作被称为"缓存锁定",缓存一致性机制会阻止同时修改由两个以上处理器缓存的内存区域数据。
2.一个处理器的缓存回写到内存会导致其他处理器的缓存无效。
一个处理器的缓存回写到内存会导致其他处理器的缓存无效。IA-32 处理器和 Iniel 64 处理器使用 MESI (修改、独占、共享、无效)控制协议去维护内部缓存和其他处理器缓存的一致性。在多核处理器系统中进行操作的时候, IA-32和Intel64处理器能嗅探其他处理器访问系统内存和它们的内部缓存。处理器使用嗅探技术保证它的内部缓存、系统内存和其他处理器的缓存的数据在总线上保持一致。例如,在 Pentium 和 P6famaly 处理器中,如果通过嗅探一个处理器来检测其他处理器打算写内存地址,而这个地址当前处干共享状态,那么正在嗅探的处理器将使它的缓存行无效,在下次访问相同内存地址时,强制执行缓存行填充
总结
1.处理器在执行lock指令时会立即将缓存中的数据同步到内存,同步时选择使用总线锁定或缓存锁定(通过缓存一致性协议实现,例如mesi协议)来保证修改操作的原子性,然后依靠缓存一致性来确保缓存中的值相同。
2.为什么有了MESI协议还需要volatile?MESI 原本是强一致性的,经过性能优化后,弱化成了最终一致性。在某些中间状态下,多个 CPU 之间的数据并不一致。同时也可能会发生乱序执行的情况,也就是重排序,volatile可以防止重排序;MESI协议数据修改完成后会先放入Load Buffer并不会直接放入内存,volatile修饰的变量在进行写操作完成后会直接同步到内存中。
java volatile是如何保证可见性的?的更多相关文章
- 在JAVA中ArrayList如何保证线程安全
[b]保证线程安全的三种方法:[/b]不要跨线程访问共享变量使共享变量是final类型的将共享变量的操作加上同步一开始就将类设计成线程安全的, 比在后期重新修复它,更容易.编写多线程程序, 首先保证它 ...
- 从根源上解析 Java volatile 关键字的实现
1.解析概览 内存模型的相关概念 并发编程中的三个概念 Java内存模型 深入剖析Volatile关键字 使用volatile关键字的场景 2.内存模型的相关概念 缓存一致性问题.通常称这种被多个线程 ...
- [Java并发编程(三)] Java volatile 关键字介绍
[Java并发编程(三)] Java volatile 关键字介绍 摘要 Java volatile 关键字是用来标记 Java 变量,并表示变量 "存储于主内存中" .更准确的说 ...
- Java volatile详解
转自:http://www.cnblogs.com/dolphin0520/p/3920373.html volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受 ...
- JAVA volatile 解析
volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以 ...
- java volatile 关键字(转)
volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以 ...
- Java volatile关键字小结
public class Test { public static void main(String[] args){ } } /* 12.3 Java内存模型 Java内存模型定义了线程与主内存之间 ...
- java 轻量级同步volatile关键字简介与可见性有序性与synchronized区别 多线程中篇(十二)
概念 JMM规范解决了线程安全的问题,主要三个方面:原子性.可见性.有序性,借助于synchronized关键字体现,可以有效地保障线程安全(前提是你正确运用) 之前说过,这三个特性并不一定需要全部同 ...
- Volatile 只保证可见性,并不保证原子性
[尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article/details/52525724 在说明Java多线程内存可见性之前,先来简单了解一下J ...
- Java Volatile相关文章目录
参考资料: http://www.google.com/cse?sa.x=0&sa.y=0&cx=010284515138798138769%3Aajbqkpwaapm&ie= ...
随机推荐
- Django框架——静态文件配置、form表单、request对象、连接数据库、ORM简介、ORM基本操作和语句
配置文件介绍 SECRET_KEY = '0yge9t5m9&%=of**qk2m9z^7-gp2db)g!*5dzb136ys0#)*%*a' # 盐 DEBUG = True # 调试模式 ...
- Python 函数及参数的使用
函数 带名字的代码块,用于完成具体的工作 关键字def定义一个函数,定义函数名,括号内是需要完成任务所需要的信息,最后定义冒号结尾 缩进构成函数体 函数调用,依次指定函数名以及冒号括起来的必要信息 d ...
- 2022-09-13:给你两个整数 m 和 n ,分别表示一块矩形木块的高和宽。 同时给你一个二维整数数组 prices ,其中 prices[i] = [hi, wi, pricei] 表示你可以
2022-09-13:给你两个整数 m 和 n ,分别表示一块矩形木块的高和宽. 同时给你一个二维整数数组 prices ,其中 prices[i] = [hi, wi, pricei] 表示你可以以 ...
- 2020-12-23:如何保证MQ的高可用?
福哥答案2020-12-23: ActiveMQ:Master-Slave 部署方式主从热备,方式包括通过共享存储目录来实现(shared filesystem Master-Slave).通过共享数 ...
- Selenium - 元素等待(2) - 显式等待/EC等待
Selenium - 元素等待 显式等待 显式等待是一种灵活的等待方式,需要声明等待的结束条件,当满足条件时会自动结束等待: 需要引入WebDriverWait包以及exception_conditi ...
- 选择结构do...while语句
// do..while语句 #include<stdio.h> int main() { int a = 0; do { a++; printf("HelloWorld\n&q ...
- Windows 安装ActiveMq5.16.6
Windows 安装ActiveMq5.16.6 前言 最近因为需要在项目中使用MQ,所以就想在我的老Windows机器上装个ActiveMq. 1. 下载安装 先到Activemq官网下载安装需要版 ...
- PHP反序列化字符逃逸 学习记录
PHP反序列化字符逃逸的原理 当开发者使用先将对象序列化,然后将对象中的字符进行过滤, 最后再进行反序列化.这个时候就有可能会产生PHP反序列化字符逃逸的漏洞. 详解PHP反序列化字符逃逸 过滤后字符 ...
- day09-SpringCloud Sleuth+Zipkin-链路追踪
SpringCloud Sleuth+Zipkin-链路追踪 官网:spring-cloud/spring-cloud-sleuth: Distributed tracing for spring c ...
- KL变换
covariance 指两个变量的相关性:cov(x, y) =E(x y) - E(x) E(y) cov(x, y) < 0 负相关 cov(x, y) = 0 无关 cov(x, y) & ...