`

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对象。
分享到:
评论

相关推荐

    extern_volatile等修饰符的用法

    volatile修饰符用于声明一个对象可以被外部进程(操作系统、硬件或并发进程等)改变。 1. 声明volatile变量 volatile修饰的变量可以被不同的线程访问和修改,常用于像中断处理程序之类的异步进程进行内存单元访问...

    C语言中的类型修饰符

    本文将详细介绍C语言中的三种重要类型修饰符:`const`、`static` 和 `volatile`。 #### 二、`const`修饰符详解 `const`修饰符主要用于声明一个或多个变量为常量,即一旦赋值之后,其值不能被修改。`const`修饰符...

    Java访问修饰符

    final 访问修饰符表示使用此修饰符的类不能够被继承。final 变量的值只能被分配一次,不能更改。 abstract 访问修饰符 abstract 访问修饰符表示抽象类,抽象类不能被实例化。抽象类中可以定义抽象方法,抽象方法是...

    volatile的用法讲解

    2. volatile修饰符不能与const修饰符同时使用,因为volatile修饰符意味着变量的值可能会改变,而const修饰符意味着变量的值不能改变。 3. 使用volatile修饰符可能会影响编译器的优化,因此需要根据实际情况进行选择...

    Java并发编程(5)volatile变量修饰符-意料之外

    在Java编程语言中,`volatile`关键字是一个非常重要的并发控制机制,它被用来修饰类的成员变量,确保这些变量在多线程环境下的可见性和有序性。然而,使用`volatile`并非总是如我们所期望的那样简单,有时会出现一些...

    java常用的修饰符

    这些修饰符组合使用,可以帮助开发者精确地控制类和方法的行为,提高代码的可维护性和安全性。理解并熟练运用这些修饰符是成为Java开发高手的关键步骤之一。在实际编程中,应根据需求选择合适的访问级别和行为特性,...

    loveincode#notes#volatile变量修饰符1

    这就可能造成一个线程在主存中修改了一个变量的值,而另一个线程还在继续使用它在寄存器中的变量值的拷贝,造成数据的不一致。volatile是一种稍弱的同步机制,在访

    java修饰符介绍

    在Java编程语言中,修饰符是用来限制或指定代码元素(如类、方法、变量)的访问权限、特性或行为的关键词。以下是对标题和描述中提及的Java修饰符及其相关知识点的详细介绍: 1. 类的访问控制修饰符: - **public*...

    java修饰符使用很给力

    在实际开发中,明智地选择和使用这些修饰符对于代码的可维护性、安全性以及性能优化至关重要。合理地控制访问权限,可以使你的代码更易于理解和测试,同时防止意外的修改或访问。了解和掌握这些修饰符的用法,能帮助...

    深入讲解C语言编程中volatile修饰符的作用

    在C语言编程中,`volatile`是一个非常关键的修饰符,它主要用来处理那些可能会被非预期因素(如中断服务程序、多线程环境或其他进程)改变的变量。`volatile`关键字的存在是为了通知编译器,它后面的变量的值可能会...

    JAVA访问修饰符大归纳

    根据 JAVA 访问修饰符的特性和使用范围,我们可以将其分为三类:修饰符类的访问修饰符、属性的访问修饰符和方法的修饰符。 一、修饰符类的访问修饰符 修饰符类的访问修飾符共有四种:默认、public、abstract 和...

    Java修饰符demo

    4. **volatile**:volatile修饰符确保多线程环境下的可见性和有序性。它用于标记共享变量,确保当一个线程修改了这个变量时,其他线程能够立即看到变化。 5. **synchronized**:同步修饰符,用于方法或代码块,确保...

    java修饰符

    Java提供了两种主要类型的修饰符:访问控制修饰符和非访问控制修饰符。本文将深入探讨Java的访问控制修饰符,包括`private`、`default`(也称为`friendly`)、`protected`和`public`,以及它们如何影响程序的结构和...

    c语言面试经常提问到的几个修饰符

    static:修饰符:修饰变量,函数。作用域:变量仅仅在本文件可见,函数在本文件可以被调用。static在函数内部定义的话,分配在堆中,数值保存在data段,而不是在栈中,而且只赋值一次。 extern:修饰符:修饰变量,...

    关于Java中各种修饰符与访问修饰符的说明

    Java是一种面向对象的编程语言,其中修饰符和访问修饰符是控制代码访问权限和行为的重要元素。...在实际开发中,合理使用这些修饰符可以有效地提高代码的封装性和安全性,是Java编程基础的关键部分。

    Java修饰符.pdf

    - `volatile`:挥发性修饰符,用于标记变量,确保多个线程之间的可见性并防止指令重排序。 理解并熟练运用Java修饰符是编写高质量、可维护的代码的基础。它们帮助开发者控制类和成员的可见性,保证数据安全,实现...

    C#修饰符

    C#修饰符 C#语言中,修饰符是用来定义类、方法、属性、字段等成员的访问权限、行为和特性的关键字。...通过学习C#和Java语言中的修饰符,我们可以更好地理解和使用这些关键字,从而编写更加高效、安全、灵活的程序。

    Java修饰符总结

    Java作为一种广泛使用的面向对象编程语言,其丰富的修饰符机制为程序设计提供了灵活性和控制力。本文旨在全面剖析Java中的修饰符,包括它们的特点、用法以及如何在不同场景下正确应用,帮助开发者更深入地理解Java的...

    深入浅出谈java修饰符共6页.pdf.zip

    在实际编程中,合理地使用这些修饰符对于控制代码的访问性、维护性、性能和可扩展性至关重要。Java程序员需要深入理解每个修饰符的作用,以便编写出高效、可维护的代码。然而,提供的压缩包文件"深入浅出谈java修饰...

Global site tag (gtag.js) - Google Analytics