`

关于volatile类型的变量

阅读更多
转自CSDN上面看到的一段话,个人感觉解释的比较透彻易懂,拿来学习一下:
http://topic.csdn.net/t/20060106/23/4502657.html

volatile仅仅一个不起眼的关键字  
尽管C和C++标准对于线程都明显的“保持沉默”,但它们以volatile关键字的形式,确实为多线程保留了一点特权。  

就象大家更熟悉的const一样,volatile是一个类型修饰符(type   modifier)。它是被设计用来修饰被不同线程访问和修改的变量。如果没有volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。下面我们来一个个说明。  

考虑下面的代码:  

class   Gadget  
{  
public:  
void   Wait()  
{  
while   (!flag_)  
{  
Sleep(1000);   //   sleeps   for   1000   milliseconds  
}  
}  
void   Wakeup()  
{  
flag_   =   true;  
}  
...  
private:  
bool   flag_;  
};  

上面代码中Gadget::Wait的目的是每过一秒钟去检查一下flag_成员变量,当flag_被另一个线程设为true时,该函数才会返回。至少这是程序作者的意图,然而,这个Wait函数是错误的。  
假设编译器发现Sleep(1000)是调用一个外部的库函数,它不会改变成员变量flag_,那么编译器就可以断定它可以把flag_缓存在寄存器中,以后可以访问该寄存器来代替访问较慢的主板上的内存。这对于单线程代码来说是一个很好的优化,但是在现在这种情况下,它破坏了程序的正确性:当你调用了某个Gadget的Wait函数后,即使另一个线程调用了Wakeup,Wait还是会一直循环下去。这是因为flag_的改变没有反映到缓存它的寄存器中去。编译器的优化未免有点太……乐观了。  

在大多数情况下,把变量缓存在寄存器中是一个非常有价值的优化方法,如果不用的话很可惜。C和C++给你提供了显式禁用这种缓存优化的机会。如果你声明变量是使用了volatile修饰符,编译器就不会把这个变量缓存在寄存器里——每次访问都将去存取变量在内存中的实际位置。这样你要对Gadget的Wait/Wakeup做的修改就是给flag_加上正确的修饰:  

class   Gadget  
{  
public:  
...   as   above   ...  
private:  
volatile   bool   flag_;  
};  

大多数关于volatile的原理和用法的解释就到此为止,并且建议你用volatile修饰在多个线程中使用的原生类型变量。然而,你可以用volatile做更多的事,因为它是神奇的C++类型系统的一部分。  
把volatile用于自定义类型  
volatile修饰不仅可以用于原生类型,也可以用于自定义类型。这时候,volatile修饰方式类似于const(你也可以对一个类型同时使用const和volatile)。  

与const不同,volatile的作用对于原生类型和自定义类型是有区别的。就是说,原生类型有volatile修饰时,仍然支持它们的各种操作(加、乘、赋值等等),然而对于class来说,就不是这样。举例来说,你可以把一个非volatile的int的值赋给一个volatile的int,但是你不能把一个非volatile的对象赋给一个volatile对象。  
分享到:
评论

相关推荐

    stm32 volatile变量的正确使用

    在C语言中,`volatile`是一个类型限定符,用于告知编译器不要对该变量进行优化,因为它可能在任何时候被未知的外部源更改。当一个变量被声明为`volatile`时,编译器会假设它的值可能在任意时间发生变化,因此每次...

    java入门教程:数据类型_Java理论与实践如何正确使用Volatile变量.docx

    ### Java入门教程:数据类型与正确使用Volatile变量 #### 概述 在Java编程语言中,`volatile`关键字提供了一种轻量级的同步机制,用于确保共享变量的可见性和一定程度上的线程安全性。相比于传统的锁机制如`...

    volatile的用法

    Volatile是C语言中的一个类型修饰符,用于告诉编译器该变量可能会在程序的控制之外被改变,从而禁止编译器对涉及该变量的代码做优化处理。这种用法在多线程、中断服务程序和硬件访问等场合特别重要。接下来详细说明...

    关于volatile关键字的说明以及测试

    volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如 操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行 优化,从而可以提供...

    volatile详解

    然而,如果`ptr`指向一个`volatile`类型的变量,那么编译器可能会生成以下代码: ```c int square(volatile int *ptr) { int a, b; a = *ptr; b = *ptr; return a * b; } ``` 如果`ptr`指向的值在两次...

    const和volatile分析

    在C++编程语言中,`const`和`volatile`是两个非常重要的关键字,它们用于修饰变量,赋予变量特殊的属性。这两个关键字在理解程序的行为、内存模型以及多线程编程中起到至关重要的作用。在此,我们将深入探讨`const`...

    Java并发编程系列- volatile

    然而,`volatile`关键字能防止特定类型的指令重排,确保在多线程环境下,对`volatile`变量的读写操作遵循一定的顺序。具体来说,如果一个操作发生在`volatile`写操作之前,那么这个操作的效应对于后续的`volatile`读...

    volatile使用详解

    `volatile` 是一种类型修饰符,用于声明的变量表示这类变量可能会被某些因素(如操作系统、硬件或其他线程)更改,这些更改是编译器所不知道的。在程序设计中,尤其是在并发编程和硬件交互中,`volatile` 关键字具有...

    extern_volatile等修饰符的用法

    在C++语言中,extern、volatile、const、static等修饰符都是非常重要的,它们可以影响变量的存储方式、生命周期和访问权限等。本文将详细介绍这些修饰符的用法和特点。 一、const修饰符 const修饰符用于声明常量,...

    CC++ Volatile关键词剖析1

    `volatile`是一个类型修饰符,用于告诉编译器某个变量的值可能会被程序外部的某些因素(如硬件中断、多线程环境或其他异步事件)改变,因此编译器不能对这个变量进行优化,每次访问时都需要从内存读取最新值。...

    深入理解 volatile 关键字.doc

    其意思是说,变量不能和其他变量一起参与判断,无论其他变量是否是volatile类型的变量。例如if(a && b)这个判断就无法满足volatile的第二条规则,会发生线程安全问题,即使这两个变量都是volatile类型的变量。 ...

    解开Volatile的面纱V1.1

    在实际开发中,`volatile`关键字通常用于标记那些不需要同步块保护的、多个线程共享的、状态标志类型的变量,如线程中断标志、单例模式中的`Singleton`实例等。但需要注意的是,`volatile`关键字并不能保证复合操作...

    volatile源码分析1

    x86处理器有L1、L2、L3缓存,以及多核之间的缓存一致性协议(如MESI协议),这些机制共同保证了多核环境下volatile变量的正确传播和一致性。 总结来说,volatile关键字通过禁止指令重排序和提供内存可见性,确保了...

    深入探讨Java多线程中的volatile变量

    例如,如果一个变量是volatile类型的,并且有多个线程同时进行增加操作(如x++),那么这个操作就不是原子性的,可能造成数据的不一致。在这种情况下,仍需要使用`synchronized`关键字或者`java.util.concurrent`...

    Java并发编程:volatile关键字解析

    这意味着当一个线程修改了一个`volatile`变量后,其他线程读取该变量时,不仅能看到该变量的最新值,还能看到在此之前这个线程所做的其他所有操作。 - **非原子性**:需要注意的是,虽然`volatile`关键字提供了可见...

    多方面解读Java中的volatile关键字.rar

    3. **原子性**:`volatile`不具备原子性,这意味着对`volatile`变量的非基本类型(如数组或对象引用)的赋值操作可能不是原子的。例如,如果你有一个`volatile`整型变量,并且两个线程同时对其进行加一操作,结果...

    static,const,volatile用法

    - 当一个变量代表了硬件寄存器的状态时,如果硬件可能会直接修改这个寄存器,则应该将这个变量声明为 `volatile` 类型,以确保读取到的是最新的值。 #### 示例代码解析 考虑以下代码片段: ```c #include int ...

    volatile关键字详解

    1. **基本概念**:`volatile`是一个类型修饰符,用于声明可能被编译器未知因素更改的变量,这些因素包括但不限于操作系统、硬件或其它线程。 2. **内存与缓存一致性**:`volatile`变量要求在每次获取其值时直接从...

Global site tag (gtag.js) - Google Analytics