简体   繁体   English

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

[英]What is the purpose of 'volatile' keyword in C#

What is the purpose of volatile keyword in C#? 在C#中volatile关键字的目的是什么?

Where would I need to use this keyword? 我需要在哪里使用此关键字?

I saw the following statement, but I am unable to understand why volatile is required here? 我看到以下声明,但我无法理解为什么需要使用volatile

internal volatile string UserName; 

I refer you to section 10.5.3 of the specification, which states: 我将引用您的规范10.5.3节,其中规定:

For non-volatile fields, optimization techniques that reorder instructions can lead to unexpected and unpredictable results in multi-threaded programs that access fields without synchronization such as that provided by the lock-statement (§8.12). 对于非易失性字段,重新排序指令的优化技术可能会在多线程程序中导致意外和不可预测的结果,这些程序无需同步即可访问字段,例如lock-statement(第8.12节)提供的字段。 These optimizations can be performed by the compiler, by the run-time system, or by hardware. 这些优化可以由编译器,运行时系统或硬件执行。 For volatile fields, such reordering optimizations are restricted: 对于易失性字段,此类重新排序优化受到限制:

A read of a volatile field is called a volatile read. 读取volatile字段称为volatile读取。 A volatile read has “acquire semantics”; 易失性读取具有“获取语义”; that is, it is guaranteed to occur prior to any references to memory that occur after it in the instruction sequence. 也就是说,保证在指令序列之后发生的任何内存引用之前发生。

A write of a volatile field is called a volatile write. 写入易失性字段称为易失性写入。 A volatile write has “release semantics”; 易失性写入具有“释放语义”; that is, it is guaranteed to happen after any memory references prior to the write instruction in the instruction sequence. 也就是说,保证在指令序列中的写指令之前的任何存储器引用之后发生。

These restrictions ensure that all threads will observe volatile writes performed by any other thread in the order in which they were performed. 这些限制确保所有线程将按照执行顺序观察由任何其他线程执行的易失性写入。 A conforming implementation is not required to provide a single total ordering of volatile writes as seen from all threads of execution. 从所有执行线程看,不需要符合要求的实现来提供易失写入的单个总排序。

Read that extremely carefully if you have any intention of ever making a volatile field. 如果您有意创造一个不稳定的领域,请仔细阅读。 If you do not completely and thoroughly understand all the implications of volatile semantics then do not attempt to use them. 如果您没有完全彻底地理解volatile语义的所有含义,那么不要尝试使用它们。 It is usually far better to use a lock, which automatically gives you sufficient memory barriers to ensure the necessary acquire and release semantics. 使用锁通常要好得多,它会自动为您提供足够的内存屏障,以确保必要的获取和释放语义。 Remember, locks are only really expensive when they are contended. 请记住,当争用时,锁只是非常昂贵。

Volatile is used for a variable that can change without your action while your code is running. Volatile用于在代码运行时可以在没有您的操作的情况下更改的变量。 It tells the compiler to write the assembly in such a way as to not ever cache the variable, but to instead be sure to read it before every use. 它告诉编译器以不会缓存变量的方式编写程序集,而是确保在每次使用之前读取它。

An example of something that would be volatile would be a hardware register that your code has memory mapped and is reading to determine when a flag is set. 一个易失性的例子是你的代码有内存映射的硬件寄存器,并且正在读取以确定何时设置了一个标志。 The hardware may set the value while your code is running and without using the volatile keyword you would not notice this change as the assembly would not ever actually check the value. 硬件可以在代码运行时设置值,而不使用volatile关键字,您不会注意到此更改,因为程序集实际上不会实际检查该值。

Volatile is a hint for the compiler (and ngen/jit compiler) that the value of this variable can change at any moment, and thus optimizations around accessing the variable by caching the value locally volatile be disabled. Volatile是编译器(和ngen / jit编译器)的暗示,该变量的值随时都可以更改,因此禁用通过缓存本地volatile的值来访问变量的优化。

Consider the following code: 请考虑以下代码:

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

If volatile was not present, the compiler might generate IL where it stores the reference on the stack for the first comparison and than reuses it for the second one. 如果不存在volatile,则编译器可能会生成IL,它将引用存储在堆栈中以进行第一次比较,而不是将其重用于第二次比较。 However, adding volatile tells the compiler that the reference might be changed by another thread, thus forcing it to generate IL that will not reuse the stack copy from the first comparison. 但是,添加volatile会告诉编译器引用可能会被另一个线程更改,从而迫使它生成不会从第一次比较中重用堆栈副本的IL。

MSDN will summarize better than I.... MSDN总结会比我好....

"The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time. Fields that are declared volatile are not subject to compiler optimizations that assume access by a single thread. This ensures that the most up-to-date value is present in the field at all times." “volatile关键字表示某个字段可能被同时执行的多个线程修改。声明为volatile的字段不受编译器优化的影响,这些优化假定单个线程访问。这可以确保最多的线程。日期值始终存在于该字段中。“

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

It indicates that the value may get changed by a different thread, so the value needs to be read even if a previous instruction has already read it. 它表示该值可能会被另一个线程更改,因此即使先前的指令已经读取了该值,也需要读取该值。

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

It is nothing but telling to compiler that this variable will change its value at anytime by means of anything and compiler should not make any assumption about this variable. 它只是告诉编译器这个变量会随时通过任何东西改变它的值,编译器不应该对这个变量做任何假设。

Normally compiler will assume that some variable will be constant during runtime. 通常编译器会假设某些变量在运行时会保持不变。 This may lead error in checking a registor value repeatedly. 这可能导致重复检查registor值的错误。 Because the register value may be changed by anything. 因为寄存器值可能会被任何改变。 So for these kind of variables should be declared 'volatile' and it be checked each time appears in the code with out any assumption. 因此,对于这些类型的变量,应该声明为“volatile”,并且每次出现在代码中都要进行检查,不做任何假设。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM