不知各位對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使用時機?的更多相关文章

  1. [读书笔记]java中的volatile关键词

    以下内容大多来自周志明的<深入理解Java虚拟机>. 当一个变量被volatile修饰后,它将具备两种特性: 1. 保证此变量对所有线程的可见性,这里的“可见性”是指当一条线程修改了这个变 ...

  2. zz剖析为什么在多核多线程程序中要慎用volatile关键字?

    [摘要]编译器保证volatile自己的读写有序,但由于optimization和多线程可以和非volatile读写interleave,也就是不原子,也就是没有用.C++11 supposed会支持 ...

  3. C语言中关键字volatile的含义【转】

    本文转载自:http://m.jb51.net/article/37489.htm 本篇文章是对C语言中关键字volatile的含义进行了详细的分析介绍,需要的朋友参考下 volatile 的意思是“ ...

  4. java多线程中的volatile和synchronized

    package com.chzhao; public class Volatiletest extends Thread { private static int count = 0; public ...

  5. java中的volatile关键字

    java中的volatile关键字 一个变量被声明为volatile类型,表示这个变量可能随时被其他线程改变,所以不能把它cache到线程内存(如寄存器)中. 一般情况下volatile不能代替syn ...

  6. java中的Volatile 变量

    Java 语言中的 volatile 变量可以被看作是一种 “程度较轻的 synchronized”:与 synchronized 块相比,volatile 变量所需的编码较少,并且运行时开销也较少, ...

  7. C/C++中的volatile简单描述

    首先引入一篇博客: 1. 为什么用volatile? C/C++ 中的 volatile 关键字和 const 对应,用来修饰变量,通常用于建立语言级别的 memory barrier.这是 BS 在 ...

  8. C和C++中的volatile、内存屏障和CPU缓存一致性协议MESI

    目录 1. 前言2 2. 结论2 3. volatile应用场景3 4. 内存屏障(Memory Barrier)4 5. setjmp和longjmp4 1) 结果1(非优化编译:g++ -g -o ...

  9. 单例模式中的volatile关键字

    在之前学习了单例模式在多线程下的设计,疑惑为何要加volatile关键字.加与不加有什么区别呢?这里我们就来研究一下.单例模式的设计可以参考个人总结的这篇文章   背景:在早期的JVM中,synchr ...

随机推荐

  1. if语句基本结构以及基础案例演示

    1.结构 if(比较表达式1) { 语句体1; }else if(比较表达式2) { 语句体2; }else if(比较表达式3) { 语句体3; } ... else { 语句体n+1; } 2.执 ...

  2. C++中的抽象类和接口

    1,在 C++ 语言中,并不直接支持面向对象中的抽象类和接口概念,但是 C++ 语言 却可以间接实现这些概念: 2,什么是抽象类: 1,面向对象中的抽象(其实就是分类)概念: 1,在进行面向对象分析时 ...

  3. java收藏的技术资料链接

    TCP三次握手详解: https://blog.csdn.net/baiyan3212/article/details/81302448 ICE通信: https://blog.csdn.net/zh ...

  4. IIS Express 不允许的父路径

    IIS Express 启动一个asp的网站,出现一个错误 Active Server Pages 错误 'ASP 0131' 不允许的父路径 对于IIS可以在可视化的IIS Manager中配置: ...

  5. JS面向对象——组合使用构造函数模型与原型模型中的隐患

    组合使用构造函数模型和原型模型中的问题,使用对象字面量重写原型模型会有隐患(涉及到原型的动态性),如下例: <!DOCTYPE html> <html> <head> ...

  6. Linux 定时任务 Crontab 命令详解

    linux 系统则是由 cron (crond) 这个系统服务来控制的.Linux 系统上面原本就有非常多的计划性工作,因此这个系统服务是默认启动的.另 外, 由于使用者自己也可以设置计划任务,所以, ...

  7. Codeforces 1195E. OpenStreetMap (单调队列)

    题意:给出一个n*m的矩形.询问矩形上所有的a*b的小矩形的最小值之和. 解法:我们先对每一行用单调栈维护c[i][j]代表从原数组的mp[i][j]到mp[i][j+b-1]的最小值(具体维护方法是 ...

  8. 42th 逻辑的连续性 取决于 细节的理解-------------我是个厨子:类的调用vs 对象调用方法

    类的调用vs 对象调用方法   class Cook5:    '''这是一个厨师的类'''        # 类是一系列对象相同的特征与技能的结合体        # 用变量表示特征(属性)    ...

  9. shell读取文件第一行和最后一行,小数的运算比较

    1. 读取文件的第一行:head -n +1 file.txt 读取文件的最后一行: tail -n -1 file.txt echo 12:30:55 | cut -d: -f 1 结果为12,意思 ...

  10. setTimeout()和setInterval()的用法及区别

    setInterval 方法表示每间隔一段时间执行一次函数,会一直执行下去,除非手动 clearInterval 来停止. var i = 10; var timer = setInterval(() ...