C#中'volatile'关键字的目的是什么?

时间:2010-11-05 03:39:12

标签: c# multithreading volatile

C#中volatile关键字的用途是什么?

我需要在哪里使用此关键字?

我看到以下声明,但我无法理解为什么这里需要volatile

internal volatile string UserName; 

6 个答案:

答案 0 :(得分:28)

我将引用您的规范10.5.3节,其中指出:

  

对于非易失性字段,优化   重新排序指令的技术   会导致意外和   不可预知的结果   访问的多线程程序   没有同步的字段,例如   由lock语句提供的   (§8.12)。这些优化可以   由编译器执行,由   运行时系统,或硬件。对于   易变的领域,这种重新排序   优化受到限制:

     

一个   读取volatile字段称为a   易读。易失性读取有   “获得语义学”;就是这样   保证在任何之前发生   对之后发生的内存的引用   它在指令序列中。

     

一个   写一个易失性字段称为a   易失写。易失性写入   “释放语义”;就是这样   保证在任何记忆之后发生   写入之前的参考   指令中的指令   序列。

     

这些限制可确保   所有线程都会观察到volatile   由任何其他线程执行的写入   按照他们的顺序   执行。一致的实施   不需要提供单个   易失写入的总排序为   从所有执行线程中看到。

如果您有意创建一个易变的字段,请非常仔细地阅读 。如果您没有完全彻底了解易失性语义的所有含义,那么请不要尝试使用它们。使用锁通常要好得多,它会自动为您提供足够的内存屏障,以确保必要的获取和释放语义。请记住,当争用时,锁只会非常昂贵。

答案 1 :(得分:7)

Volatile用于在代码运行时无需操作即可更改的变量。它告诉编译器以不会缓存变量的方式编写程序集,而是确保在每次使用之前读取它。

一个易失性的例子是你的代码有内存映射的硬件寄存器,它正在读取以确定何时设置了一个标志。硬件可能会在代码运行时设置值,而不使用volatile关键字,您不会注意到此更改,因为程序集实际上不会检查该值。

答案 2 :(得分:6)

Volatile是编译器(和ngen / jit编译器)的一个暗示,这个变量的值随时都可以改变,因此禁用通过缓存本地volatile的值来访问变量的优化。

请考虑以下代码:

If (UserName == "")
    // do something
If (UserName == "Fred")
    // do something

如果volatile不存在,编译器可能会生成IL,它会将引用存储在堆栈中以进行第一次比较,而不是将其重用于第二次比较。但是,添加volatile会告诉编译器引用可能会被另一个线程更改,从而迫使它生成不会重复使用第一次比较的堆栈副本的IL。

答案 3 :(得分:4)

MSDN将比我更好地总结....

  

“volatile关键字表示某个字段可能被同时执行的多个线程修改。声明为volatile的字段不受编译器优化的影响,这些优化假定单个线程访问。这可以确保最多日期值始终存在于该字段中。“

http://msdn.microsoft.com/en-us/library/x13ttww7(v=VS.100).aspx

答案 4 :(得分:3)

它表示该值可能会被另一个线程更改,因此即使前一条指令已经读取了该值,也需要读取该值。

http://msdn.microsoft.com/en-us/library/x13ttww7%28VS.71%29.aspx

答案 5 :(得分:2)

这只是告诉编译器这个变量 将通过任何方式随时改变其价值 编译器不应该对这个变量做任何假设。

通常编译器会假设某个变量是 运行期间常量。这可能会导致检查错误 registor值反复。因为寄存器值可能 什么都改变了。所以对于这些变量 应该被声明为“易变”并且每次都要进行检查 出现在代码中没有任何假设。