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

Zai*_*ikh 17 c# multithreading volatile

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

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

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

internal volatile string UserName; 
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 29

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

对于非易失性字段,重新排序指令的优化技术可能会在多线程程序中导致意外和不可预测的结果,这些程序无需同步即可访问字段,例如lock-statement(第8.12节)提供的字段.这些优化可以由编译器,运行时系统或硬件执行.对于易失性字段,此类重新排序优化受到限制:

读取volatile字段称为volatile读取.易失性读取具有"获取语义"; 也就是说,保证在指令序列之后发生的任何内存引用之前发生.

写入易失性字段称为易失性写入.易失性写入具有"释放语义"; 也就是说,保证在指令序列中的写指令之前的任何存储器引用之后发生.

这些限制确保所有线程将按照执行顺序观察由任何其他线程执行的易失性写入.从所有执行线程看,不需要符合要求的实现来提供易失写入的单个总排序.

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

  • 好的,这是一个很好的解释.(Y) (2认同)

w.d*_*hue 7

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

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


Fra*_*nov 6

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

请考虑以下代码:

If (UserName == "")
    // do something
If (UserName == "Fred")
    // do something
Run Code Online (Sandbox Code Playgroud)

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