[轉]C/C++中的volatile使用時機?
不知各位對volatile(揮發性的)這個字陌不陌生? 我相信大家在一些程式或多或少都看
過這個字眼, 但是究竟要在何種場合用它呢?
.當然一定是有需要, C/C++才會有這個保留字, 否則只是增加programmer的困擾而已
.有2兩個場合(I/O & multithread program), 供各位參考!
.請大家check自己的程式中(尤其是第2個場合), 若有的話請記得加上volatile
1. I/O, 假設有一程式片斷如下
U8 *pPort;
U8 i, j, k;
pPort = (U8 *)0x800000;
i = *pPort;
j = *pPort;
k = *pPort;
以上的i, j, k很有可能被compiler最佳化而導致產生
i = j = k = *pPort;
的code, 也就是說只從pPort讀取一次, 而產生 i = j = k 的結果, 但是原本的程式的目
的是要從同一個I/O port讀取3次的值給不同的變數, i, j, k的值很可能不同(例如從此
I/O port 讀取溫度), 因此i = j = k的結果不是我們所要的
怎麼辦 => 用volatile, 將
U8 *pPort;
改為
volatile U8 *pPort;
告訴compiler, pPort變數具有揮發性的特性, 所以與它有關的程式碼請不要作最佳化動作. 因而
i = *pPort;
j = *pPort;
k = *pPort;
此三列程式所產生的code, 會真正地從pPort讀取三次, 從而產生正確的結果
2. Global variables in Multithread program
=> 這是在撰寫multithread program時最容易被忽略的一部份
=> 此原因所造成的bug通常相當難解決(因為不穩定)
假設有以下程式片斷, thread 1 & thread 2共用一個global var: gData
thread 1: thread 2:
... ....
int gData; extern int gData;
while (1) int i, j, k;
{
.... for (i = 0; i < 1000; i++)
gData = rand(); {
..... /* A */
} j = gData;
....
.... }
在thread 2的for loop中, 聰明的compiler看到gData的值, 每次都重新從memory load到register,
實在沒效率, 因此會產生如下的code(注意,tmp也可以更進一步的用register取代):
tmp = gData;
for (i = 0; i < 1000; i++
{
/* A */
j = tmp;
....
}
也就是gData只讀取一次, 這下子問題來了, 說明如下:
.thread 2在執行for loop到j = gData的前一列(A)的時候(假設此時gData=tmp=5), 被切換到thread 1執行
.在thread 1的while loop中透過gData = rand(), 對gData做了修改(假設改為1), 再切換回thread 2執行
.繼續執行 j = gData, 產生j = 5的結果
.但是正確的結果應該是 j = 1
怎麼辦 => 也是用volatile,
在thread 1中, 將
int gData;
改為
volatile int gData;
在thread 2中, 將
extern int gData;
改為
extern volatile int gData;
[轉]C/C++中的volatile使用時機?的更多相关文章
- [读书笔记]java中的volatile关键词
以下内容大多来自周志明的<深入理解Java虚拟机>. 当一个变量被volatile修饰后,它将具备两种特性: 1. 保证此变量对所有线程的可见性,这里的“可见性”是指当一条线程修改了这个变 ...
- zz剖析为什么在多核多线程程序中要慎用volatile关键字?
[摘要]编译器保证volatile自己的读写有序,但由于optimization和多线程可以和非volatile读写interleave,也就是不原子,也就是没有用.C++11 supposed会支持 ...
- C语言中关键字volatile的含义【转】
本文转载自:http://m.jb51.net/article/37489.htm 本篇文章是对C语言中关键字volatile的含义进行了详细的分析介绍,需要的朋友参考下 volatile 的意思是“ ...
- java多线程中的volatile和synchronized
package com.chzhao; public class Volatiletest extends Thread { private static int count = 0; public ...
- java中的volatile关键字
java中的volatile关键字 一个变量被声明为volatile类型,表示这个变量可能随时被其他线程改变,所以不能把它cache到线程内存(如寄存器)中. 一般情况下volatile不能代替syn ...
- java中的Volatile 变量
Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”:与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少, ...
- C/C++中的volatile简单描述
首先引入一篇博客: 1. 为什么用volatile? C/C++ 中的 volatile 关键字和 const 对应,用来修饰变量,通常用于建立语言级别的 memory barrier.这是 BS 在 ...
- C和C++中的volatile、内存屏障和CPU缓存一致性协议MESI
目录 1. 前言2 2. 结论2 3. volatile应用场景3 4. 内存屏障(Memory Barrier)4 5. setjmp和longjmp4 1) 结果1(非优化编译:g++ -g -o ...
- 单例模式中的volatile关键字
在之前学习了单例模式在多线程下的设计,疑惑为何要加volatile关键字.加与不加有什么区别呢?这里我们就来研究一下.单例模式的设计可以参考个人总结的这篇文章 背景:在早期的JVM中,synchr ...
随机推荐
- u盘在电脑读不出来,但别的可以读
其实一般这种问题都是驱动程序问题导致的,解决方法很简单,不管是win7还是win10都适用: 插入u盘然后在设备管理里删掉设备重新插拔试试. 详细步骤是: 插上U盘 打开设备管理器 ...
- [fw]How to use DISM to install a hotfix from within Windows
How to use DISM to install a hotfix from within Windows Jeff Hughes (CORE) 15 Feb 2011 10:10 AM 22 H ...
- 记一次CentOS7进单用户模式修改密码的失败经历(faild to load SELinux policy freezing)
背景:Cent SO7.4root用户密码忘记,根据https://www.linuxidc.com/Linux/2016-08/134034.htm提供的放法修改完密码之后系统启动后一直停留在转圈的 ...
- bootstrap-thymeleaf-分页
1.HTML代码 <div th:fragment="paginater"> <ul th:id="paginaterUlID" th:if= ...
- microtime函数用法
/** * microtime函数 * 返回:如果参数为空,则返回字符串 "微妙部分(单位:秒) 秒",字符串的两部分都是以"秒"为单位返回的 * 如果参数为 ...
- html中插入css的4种方法
#1:链入外部样式表 <head> <link href="mystyle.css" rel="stylesheet" type=" ...
- java两个数组内存图
- python 环境变量的配置
1. 打开python安装目录 2.将python.exe重名为python3.exe 3.在环境变量的path中,添加python3的目录 4.将pip.exe的目录页添加到path中,即可完成环境 ...
- SSD的理解,为PyramidBox做准备
目标检测主流方法有两大类 two-stage,以rcnn系列为主,采用建议框的方式对目标进行预测,过程首先要经过网络生成候选框,分类背景前景与进行第一次回归,之后再进行一次精细回归. 优点是准确率高, ...
- Redis端口配置
redis.host=192.168.200.128redis.port=6379redis.pass=redis.database=0redis.maxIdle=300redis.maxWait=3 ...