volatile的介绍
volatile的介绍
来看这个代码:
int fun(int& a)
{
int b = a;
int c = a;
return a+b+c;
}
int main()
{
int a=1;
//.........做一些和a无关的事
return fun(a);
}
这个代码是很好优化的,因为编译器知道a的值是1,参考上下文,编译器又能知道b和c的值也是1,
而且根本没有人用到了a,b,c三个变量,也没有任何人在修改a,b,c三个的值,所以编译器可能就直接把这个函数优化成:int main() { return 3; }了.
这么优化有什么问题吗? 单线程没问题,但多线程就有问题了,如果是多线程,a的值虽然在当前上下文中不会被修改,但可能正在被其他线程修改啊.于是上面的优化
就不对了. 那么,volatile关键字在这里就可以帮助我们了,volatile关键字提醒编译器: a可能随时被意外修改.意外的意思是虽然当前这段代码里看起来a不会变,但可能别的地方正在修改a的值哦.所谓"别的地方",某些情况下指的就是其他线程了.
那么,如果把代码修改如下:
int fun(volatile int& a)
{
int b = a;
int c = a;
return a+b+c;
}
int main()
{
volatile int a=1;
//.........做一些和a无关的事
return fun(a);
}
编译器就不敢优化了:
int fun(volatile int& a)
{
int b = a; //这里从内存读一下a吧,谁知道a还等不等于1呢
int c = a; //这里再从内存读一下a吧,谁知道a还等不等于1呢
return a+b+c; //这里也从内存读一下a吧,谁知道a还等不等于1呢
}
int main()
{
volatile int a=1; //.........做一些和a无关的事
return fun(a); //完全不敢优化啊,鬼知道a变成多少了....
}
同理的,这段代码:
//..........
int a=0;
//做一些和a无关的事
if(a==0) doSomething();
//..........编译器会发现,a肯定等于0啊,那我还if个毛啊,直接优化掉!
//..........
int a=0;
//做一些和a无关的事
doSomething(); //if被去掉了
//..........
但,一旦添加了volatile,编译器就不敢优化了.例如:
//..........
volatile int a=0;
//做一些和a无关的事
if(a==0) doSomething(); //可不敢优化这里! 谁知道a变成多少了!
//..........
这便是volatile的作用了.
必须补充说明,volatile和锁没有一毛钱的关系,该加锁依然需要加锁.给变量添加volatile并不会让其自动拥有一个锁.所以该加锁还得加.
网上教程里经常见到双检锁保证单例模式的代码,简化一下,大概逻辑如下:
static int* instance;
int& get_instance()
{
if( !instance ) { //检查如果单例的指针是0
此处有某种锁; //则在此处上锁
if( !instance ) { //再判断一次,以防等待锁期间有别的线程已经new完了
instance = new int; //确认无误则new之
}
}
return *instance;
}
int main()
{
int& i = get_instance();
i = 111;
return 1;
}
1.volatile的主要作用是:提示编译器该对象的值有可能在编译器未监测的情况下被改变。volatile类似于大家所熟知的const也是一个类型修饰符。volatile是给编译器的指示来说明对它所修饰的对象不应该执行优化。volatile的作用就是用来进行多线程编程。在单线程中那就是只能起到限制编译器优化的作用。
2.如果没有volatile,你将无法在多线程中并行使用到基本变量。
3.如果一个基本变量被volatile修饰,编译器将不会把它保存到寄存器中,而是每一次都去访问内存中实际保存该变量的位置上。这一点就避免了没有volatile修饰的变量在多线程的读写中所产生的由于编译器优化所导致的灾难性问题。所以多线程中必须要共享的基本变量一定要加上volatile修饰符。当然了,volatile还能让你在编译时期捕捉到非线程安全的代码。
4.volatile对基本类型和对用户自定义类型的使用与const有区别,比如你可以把基本类型的non-volatile赋值给volatile,但不能把用户自定义类型的non-volatile赋值给volatile,而const都是可以的。还有一个区别就是编译器自动合成的复制控制不适用于volatile对象,因为合成的复制控制成员接收const形参,而这些形参又是对类类型的const引用,但是不能将volatile对象传递给普通引用或const引用。
5.在编写多线程程序中使用volatile的关键四点:
1).将所有的共享对象声明为volatile;
2).不要将volatile直接作用于基本类型;
3).当定义了共享类的时候,用volatile成员函数来保证线程安全;
4).多多理解和使用volatile和LockingPtr!(强烈建议)
volatile的介绍相关推荐
- [Java并发编程(三)] Java volatile 关键字介绍
[Java并发编程(三)] Java volatile 关键字介绍 摘要 Java volatile 关键字是用来标记 Java 变量,并表示变量 "存储于主内存中" .更准确的说 ...
- Java并发编程-volatile关键字介绍
前言 要学习好Java的多线程,就一定得对volatile关键字的作用机制了熟于胸.最近博主看了大量关于volatile的相关博客,对其有了一点初步的理解和认识,下面通过自己的话叙述整理一遍. 有什么 ...
- java-Transient关键字、Volatile关键字介绍和序列化、反序列化机制、单例类序列化
- Transient关键字 Java的serialization提供了一种持久化对象实例的机制.当持久化对象时,可能有一个特殊的对象数据成员,我们不想 用serialization机制来保存它.为 ...
- volatile修饰的变量_看了这篇volatile详细介绍,面试你会害怕?
前言 Java中volatile这个热门的关键字,在面试中经常会被提及,在各种技术交流群中也经常被讨论,但似乎讨论不出一个完美的结果,带着种种疑惑,准备从JVM.C++.汇编的角度重新梳理一遍. vo ...
- volatile关键字解析~高级java必问
volatile基本介绍 volatile可以看成是synchronized的一种轻量级的实现,但volatile并不能完全代替synchronized,volatile有synchronized可见 ...
- 再有人问你volatile是什么,就把这篇文章发给他
转载自 再有人问你volatile是什么,就把这篇文章发给他 在再有人问你Java内存模型是什么,就把这篇文章发给他中我们曾经介绍过,Java语言为了解决并发编程中存在的原子性.可见性和有序性问题, ...
- 漫画:什么是volatile关键字?(整合版)
转载自 永远爱大家的 程序员小灰 ----- 第二天 ----- ------------ Java内存模型简称JMM(Java Memory Model),是Java虚拟机所定义的一种抽象规范,用来 ...
- 深入理解Java中的volatile关键字
在再有人问你Java内存模型是什么,就把这篇文章发给他中我们曾经介绍过,Java语言为了解决并发编程中存在的原子性.可见性和有序性问题,提供了一系列和并发处理相关的关键字,比如synchronized ...
- 【Java并发编程 】同步——volatile 关键字
英 /ˈvɒlətaɪl/ 我了太噢(记不住单词怎么读) 一.volatile的介绍? volatile是一个轻量级的synchronized,一般作用与变量,在多处理器开发的过程中保证了内存的可见性 ...
最新文章
- about EnableEventValidation 这是什么意思,欢迎指点一下,谢谢
- android 开发
- 北京矿大计算机考研每年分数线,2021中国矿业大学北京考研国家线公布时间_国家线是多少分...
- nginx代理配置根据ip地址来转发到不同的地址端口
- K8S_Google工作笔记0012---通过二进制方式_部署master组件
- java this关键字的使用_做java两年了,构造方法和方法重载还是搞不明白?一文帮你搞定...
- linux下安装vmware tools的方法
- PHP compact
- 三菱FX3U 485ADP与东元TECO变频器N310通讯实战程序
- Gerrit项目权限设置总结
- c语言重复测试,C语言检测过零的方法--等待过零检测法
- 安卓桌面壁纸_教你一分钟定制你的个性锁屏桌面壁纸(安卓+ios)
- nape.dynamics.InteractionGroup
- ClickHouse MergeTree二级索引/跳数索引
- windows专业版升级企业版
- svd与svd++联系与区别
- pyqt5 制作壁纸切换工具实例 第二章
- 西安10万条业主信息被贩卖
- DOO-SABIN 细分正方体(2)利用半边数据结构表示(一次和两次细分)
- java中子类会继承父类的构造方法吗