Java关键字volatile的实现原理(四)
简述
volatile 是轻量级的synchronized,在多线程开发中保证了共享变量的可见性。可见性就是当一个线程修改一个共享变量时,另一个线程可以读到修改的值。如果volatile变量使用恰当,它比synchronized的使用成本更低,因为它不会引起线程上下文的切换和调度。
什么是volatile
Java语言提供了一种稍弱的同步机制,即 volatile 变量,用来确保共享变量能被多线程正确的更新和读取。当把变量声明为volatile后,编译器和运行时就会认为这个变量是共享的,因此不会把该变量的操作和其他内存操作一起重排序。volatile 变量不会被缓存在寄存器或者其他处理器不可见的地方,因此在读取volatile 修饰的变量时总会返回最新的值。
volatile 的实现原理
在了解volatile 的实现原理之前,我们先看一下与其相关的CPU术语:
| 术语 | 英文名称 | 术语描述 |
|---|---|---|
| 内存屏障 | memory barriers | 一组处理器指令,用来限制对内存操作的顺序 |
| 缓冲行 | cache line | 缓存中可以分配的最小存储单位,处理器在填写缓存行时,会加载整个缓存行,需要多个主内存读周期 |
| 原子操作 | automic operations | 不可中断的一个或一系列操作 |
| 缓冲行填充 | cache line fill | 当处理器识别到从内存中读取的操作数是可以缓存的,处理器会读取整个缓存行到适当的缓存(L1,L2,L3) |
| 缓存命中 | cache hit | 处理器从缓存中读取到了需要的数据 |
| 写命中 | write hit | 当处理器将操作数写会到缓存区域时,会先检查这个缓存的内存地址是否在缓存行中,如果存在一个有效的缓存行,则处理器将这个操作数写回到缓存,而不是写到内存,这个操作被称为 写命中 |
| 写缺失 | write misses the cache | 一个有效的缓存行被写到不存在的内存区域 |
volatile 如何保证可见性
为了提高处理速度,处理器不直接和内存进行通信,而是先将系统内存的数据读到内部缓存(L1,L2,L3或其他)后再进行操作,但是操作完不知道何时会被写到内存。
如果对声明了volatile 的变量进行写操作,JVM 就会向处理器发送一条Lock前缀的指令,将这个变量所在缓存行的数据写回到系统内存。
在多核处理器下,为了保证各个处理器的缓存是一致的,就会实现缓存一致性协议,每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是否过期,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据读到处理器缓存里。
volatile 实现原则
1、Lock 前缀的指令会引起处理器缓存回写到内存
如果访问的内存区域已经缓存在处理器内部,此时当前处理器会锁定这块内存区域的缓存并写到内存,并使用缓存一致性机制来确保修改的原子性,此操作被称为 缓存锁定,缓存一致性机制会阻止同一时间修改两个以上处理器缓存的内存区域的数据。
2、一个处理器的缓存回写到内存会导致其他处理器的缓存失效
处理器使用嗅探技术保证它的内部缓存、系统内存 和 其他处理器的缓存的数据在总线上保持一致。如果通过嗅探一个处理器来检测其他处理器打算写内存地址,而这个内存地址当前处于共享状态,那么正在嗅探的处理器将使它的缓存行无效,在下次访问相同内存地址是,强制执行缓存行填充。
volatile 的局限性
虽然volatile变量使用很方便,但也存在一些局限性。volatile变量通常用作某个操作完成、发生中断或者状态的标志。尽管volatile 变量也可以用于表示其他的状态信息,但在使用时要非常小心。例如:volatile 的语义不足以确保递增操作(count++)的原子性,除非能确保只有一个线程对变量进行写操作。
加锁机制既可以确保可见性又可以确保原子性,而volatile 变量只能确保可见性。
当满足以下所有条件时,才应该使用volatile 变量:
1、对变量的写入操作不依赖于变量的当前值,或者确保只有一个线程更新变量的值
2、该变量不会与其它变量一起作为不变性条件
3、在访问变量时不需要加锁
Java关键字volatile的实现原理(四)的更多相关文章
- java 关键字volatile
一.Java内存模型 想要理解volatile为什么能确保可见性,就要先理解Java中的内存模型是什么样的. Java内存模型规定了所有的变量都存储在主内存中.每条线程中还有自己的工作内存,线程的工作 ...
- JAVA关键字Volatile的特性
一.简述: 关键字Volatile是JAVA虚拟机提供的最轻量级的同步机制,但是它并不容易完全被正确.完整的理解,以致于许多程序员在遇到需要处理多线程数据竞争的时候一律使用synchronized来进 ...
- Java 关键字volatile的解释
volatile 关键字特征: 1.可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的.可以禁止线程的工作内存对volatile修饰的变量进行缓存,并将修改的变量立即写入主存. 2. ...
- Java关键字-volatile
关键字volatile可以说是Java虚拟机提供的最轻量级的同步机制. 一旦某个共享变量(类的成员变量.类的静态成员变量)被volatile修饰之后,那么就具备了两层语义: 1.保证了不同线程对这个变 ...
- java关键字volatile用法详解
volatile关键字想必大家都不陌生,在java 5之前有着挺大的争议,在java 5之后才逐渐被大家接受,同时作为java的关键字之一,其作用自然是不可小觑的,要知道它是java.util.con ...
- 深入汇编指令理解Java关键字volatile
volatile是什么 volatile关键字是Java提供的一种轻量级同步机制.它能够保证可见性和有序性,但是不能保证原子性 可见性 对于volatile的可见性,先看看这段代码的执行 flag默认 ...
- 关于 Java 关键字 volatile 的总结
1 什么是 volatile volatile 是 Java 的一个关键字,它提供了一种轻量级的同步机制.相比于重量级锁 synchronized,volatile 更为轻量级,因为它不会引起线程上下 ...
- Java内存模型及Java关键字 volatile的作用和使用说明
先来看看这个关键字是什么意思:volatile [ˈvɒlətaɪl] adj. 易变的,不稳定的; 从翻译上来看,volatile表示这个关键字是极易发生改变的.volatile是java语言中, ...
- Java 关键字volatile 与 synchronized 作用与区别
1,volatile 它所修饰的变量不保留拷贝,直接访问主内存中的. 在Java内存模型中,有main memory,每个线程也有自己的memory (例如寄存器).为了性能,一个线程会在自己 ...
随机推荐
- oracle用户解锁,rename管理
---查看命令:用户默认表空间 SYS@ACE >select username,default_tablespace,temporary_tablespace,created from dba ...
- image的路径写法格式
if (MapGrid.Visibility == Visibility.Visible) { this.MapGrid.Visibility = Visibility.Collapsed; ...
- C#Random随机值重复的解决方法
使用如上图所示的代码,将会出现如下情况,明明是随机,可值都是同样的,这样的随机几率也太小了,所以估计是代码有问题. 于是搜索了下,发现引起这个问题的原因是C#中的Random是根据时间来产生随机数,而 ...
- HTML练习二--动态加载轮播图片
接上一篇https://www.cnblogs.com/shuaimeng/p/11106655.html demo下载: https://pan.baidu.com/s/1dhvzHwTHKiguy ...
- c# redis密码验证笔记
参考博客https://www.cnblogs.com/qukaicheng/p/7514168.html写的 安装教程https://www.redis.net.cn/tutorial/3503.h ...
- Nginx用法详解
nginx作为一个高性能的web服务器,想必大家垂涎已久,蠢蠢欲动,想学习一番了吧,语法不多说,网上一大堆.下面博主就nginx的非常常用的几个功能做一些讲述和分析,学会了这几个功能,平常的开发和部署 ...
- JavaScript02
一. 判断// 三元表达式// 循环// 判断: 用的最多的就是if判断// 1.// if(条件){// 当条件满足以后执行的语句// } // 2.// if(条件){// // }else{// ...
- JDBC 插入时间字段的值
ps.setTimestamp(6, new Timestamp(System.currentTimeMillis()));
- ELK 错误: retrying failed action with response code: 403, kibana无log显示
今天10点时候同事报出kibana突然不显示log了,开始紧急排查 1. 从数据源头查起,先看被filebeat监视的log文件是否在更新(一般只要log对应服务在正常运行,log文件中就会有数据持续 ...
- C# 对象遍历 string类型 null转空字符串和去前后空格
using System; using System.Collections.Generic; namespace OA.Common.Extensions { /// <summary> ...