What is volatile?
What is volatile?
一次偶然的机会(java多线程电梯作业寻求多个进程分享变量的方法),接触到了volatile,因此我查阅了相关的材料,对这部分做了一些了解,在这里和大家分享一下。
首先,我们先来聊一聊几个概念
1、What is reorder
编译器和JVM通过改变程序的处理顺序来优化程序,用于提高程序性能的方式。
多线程程序设计中,重排序会导致运行错误。
举个栗子:
class Compare {
private int x = 0;
private int y = 0;
public void write() {
x = 100;
y = 50;
}
public boolean compare() {
return x<y
}
}
public class Main {
public static void main(String[] args) {
final Compare com = new Compare();
new Thread() {
public void run() {
com.write();
}
}.start();
new Thread() {
public void run() {
com.read();
}
}.start();
}
}
让人吃惊的是,x<y居然真的存在true的情况
原因就在于重排序
编译器的优化策略可能会改变x,y的赋值顺序,导致x<y
显然,我们可以通过synchronized来解决这个问题
2、What is visibility
线程A将某个值写入字段x,线程B读到了这个值
多线程中的可见性问题来源于normal read/write操作是通过缓存在执行的,read到的不一定是最新值,write的也不一定立即对其他线程可见
而synchronized是解决这一问题的有效方法,相信大家也并不陌生,具体用法可以参考我的另一篇博客
其实,volatile也是一种不错的方法
3、What is atomicity
不可分割的操作,例如某线程正在执行synchronized方法,其他线程无法进入该方法,从多线程的角度,这就是原子操作。
Java定义了一些原子操作:primitive type(char、int)的赋值和引用,对象等引用类型的赋值和引用
但是long与double的操作不是原子的,在线程共享时需要放入synchronized
now,进入正题
Volatile
Make sure that a given variable is read directly from main memory and always written back to main memory when updated
volatile具有同步处理(参考sunchronization)和对long和double的原子操作这两种功能
同步处理
1、如果线程A向volatile字段写入的值对线程B可见,那么之前向其他字段写入的值都是对B可见
2、向volatile字段读取和写入前后不会发生重排序
看到这里,我们发现重排序和可见性的问题好像都被volatile解决了
在这里,我们来看一段代码,深入理解一下同步处理
class TryVolatile {
private int num = 0;
private volatile boolean valid = false;
public void write() {
num = 1;
valid = true;
/*
*1、不会被重排序
*2、线程B中valid会为true
*3、线程B可能出现num=1
*/
}
public void read() {
if (valid) {
System.out.println(this.num);
}
}
}
public class Main {
public static void main(String[] args) {
final tryVolatile = new TryVolatile;
new Thread() {
public void run() {
tryVolatile.write();
}
}.start();
new Thread() {
public void run() {
tryVolatie.read();
}
}.start();
}
}
总结一下volatile的使用:
1、volatile字段赋值语句位置很重要!!!(可以运行上面的代码观察
2、volatile不会进行线程互斥处理(volatile字段不会进入等待队列
3、访问volatile字段会产生性能开销(参考synchronized
对long和double的原子操作
tip:
java.util.concurrent.atomic包提供了原子操作编程的类,例如AtomicInteger、AtomicLong、AtomicIntegerArray等,都是通过封装volatile得到的
What is volatile?的更多相关文章
- 多线程同步工具——volatile变量
关于volatile,找了一堆资料看,看完后想找一个方法去做测试,测了很久,感觉跟没有一样. 这本书<深入理解Java内存模型>,对volatile描述中有这样一个比喻的说法,如下代码所示 ...
- Java并发编程:volatile关键字解析
Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...
- 多线程中的volatile和伪共享
伪共享 false sharing,顾名思义,“伪共享”就是“其实不是共享”.那什么是“共享”?多CPU同时访问同一块内存区域就是“共享”,就会产生冲突,需要控制协议来协调访问.会引起“共享”的最 ...
- volatile
Volatile修饰的成员变量在每次被线程访问时,都强迫从共享内存中重读该成员变量的值.而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存.这样在任何时刻,两个不同的线程总是看到某个成员变量的 ...
- c#下volatile关键字
volatile多用于多线程的环境,当一个变量定义为volatile时,读取这个变量的值时候每次都是从momery里面读取而不是从cache读.这样做是为了保证读取该变量的信息都是最新的,而无论其 ...
- Java并发之原子变量和原子引用与volatile
我们知道在并发编程中,多个线程共享某个变量或者对象时,必须要进行同步.同步的包含两层作用:1)互斥访问(原子性):2)可见性:也就是多个线程对共享的变量互斥地访问,同时线程对共享变量的修改必须对其他线 ...
- 单例模式中用volatile和synchronized来满足双重检查锁机制
背景:我们在实现单例模式的时候往往会忽略掉多线程的情况,就是写的代码在单线程的情况下是没问题的,但是一碰到多个线程的时候,由于代码没写好,就会引发很多问题,而且这些问题都是很隐蔽和很难排查的. 例子1 ...
- volatile修饰符
Volatile 修饰的成员变量在每次被线程访问时,都强制从共享内存中重新读取该成员变量的值.而且,当成员变量发生变化时,会强制线程将变化值回写到共享内存.这样在任何时刻,两个不同的线程总是看到某个成 ...
- Java的多线程机制系列:不得不提的volatile及指令重排序(happen-before)
一.不得不提的volatile volatile是个很老的关键字,几乎伴随着JDK的诞生而诞生,我们都知道这个关键字,但又不太清楚什么时候会使用它:我们在JDK及开源框架中随处可见这个关键字,但并发专 ...
- java中关键字volatile的作用
用在多线程,同步变量. 线程为了提高效率,将某成员变量(如A)拷贝了一份(如B),线程中对A的访问其实访问的是B.只在某些动作时才进行A和B的同步.因此存在A和B不一致的情况.volatile就是用来 ...
随机推荐
- 使用SpringSecurity体验OAUTH2之一 (入门1)
OAUTH2是一种安全的授权框架,其原理在网上有许多文章上可以看到.但从实践角度,好的文章比较少.SpringSecurity框架本身是支持OAUTH2的,所以下面通过使用SpringSecurity ...
- 生成透视列之for xml path
临时表#t原始数据: 实现如下格式,即根据Province分组,把每个组对应的City列以某种格式展示: 实现方法: select t.Province,(select city+',' From # ...
- WEB部分题目writeup
MEIZIJIU_PHP 题目链接: http://202.112.51.184:20001/ 打开网页出现一段PHP代码: 代码大意就是如果得到的code不为空则执行下列操作: 如果code长度大于 ...
- docker简单介绍----Dockerfile命令
DockerFile的组成部署: 下面优先介绍下Dcokerfile的基础指令 一.CMD指令:容器启动时要莫热门运行的命令,如果有多个CMD指定,最后一个生效 使用方法: CMD ["ex ...
- SpringBoot整合Swagger测试api构建
@Author:SimpleWu 什么是Swagger? Swagger是什么:THE WORLD'S MOST POPULAR API TOOLING 根据官网的介绍: Swagger Inspec ...
- python3+Robot Framework+PyCharm环境部署及执行脚本
Robot Framework是一个非常优秀的开源关键字驱动自动化测试框架,目前已经支持python2和python3,但是GUI界面RIDE只支持python2,但是python的未来是python ...
- ubuntu18.04使用SPFlashTool提示缺少libpng12.so.0
Ubuntu libpng12无法安装解决 Ubuntu 14以上就已经不再支持libpng12,然而有些软件又依赖于libpng12(如我要使用的Cisco Packet Tracer).我们可以采 ...
- iOS webview 获取html中的图片地址
//js代码,声明1个数组,对img 进行遍历,采用,分割多个url NSString * getAllImages = @"var str = new Array();" &qu ...
- Mac安装nginx配置过程
mac电脑系统重装了,记录一下安装nginx的过程: 1.打开终端 2.安装Command Line tools xcode-select --install 3.安装brew命令 ruby -e & ...
- python第十五天
什么是模块? 一系列功能的集合 定义模块? 创建一个py文件就是一个模块,该py文件名就是模块名 怎么使用模块? 在要是用的模块文件中通过import 模块名 来导入模块 模块的四种方式? 1.编译执 ...