什么时候应该在 C# 中使用 volatile 关键字?

什么时候应该在 C# 中使用 volatile 关键字?

问题描述:

谁能很好地解释 C# 中的 volatile 关键字?它解决了哪些问题,没有解决哪些问题?在哪些情况下它可以节省我使用锁定?

Can anyone provide a good explanation of the volatile keyword in C#? Which problems does it solve and which it doesn't? In which cases will it save me the use of locking?

我认为没有比 Eric Lippert(强调原文):

I don't think there's a better person to answer this than Eric Lippert (emphasis in the original):

在 C# 中,volatile"不仅意味着确保编译器和jitter 不执行任何代码重新排序或寄存器缓存对此变量的优化".这也意味着告诉处理器做他们需要做的任何事情以确保我正在阅读最新值,即使这意味着停止其他处理器并制作它们将主内存与缓存同步".

In C#, "volatile" means not only "make sure that the compiler and the jitter do not perform any code reordering or register caching optimizations on this variable". It also means "tell the processors to do whatever it is they need to do to ensure that I am reading the latest value, even if that means halting other processors and making them synchronize main memory with their caches".

实际上,最后一点是谎言.易失性读取的真正语义并且写入比我在这里概述的要复杂得多;在事实上他们实际上并不能保证每个处理器都会停止它正在执行并将缓存更新到/从主内存.相反,他们提供关于读取前后内存访问方式的较弱保证可以观察到写入相对于彼此是有序的.某些操作,例如创建新线程、输入锁或使用 Interlocked 系列方法中的一种引入更强的保证观察排序.如果您想了解更多详情,阅读 C# 4.0 规范的 3.10 和 10.5.3 部分.

Actually, that last bit is a lie. The true semantics of volatile reads and writes are considerably more complex than I've outlined here; in fact they do not actually guarantee that every processor stops what it is doing and updates caches to/from main memory. Rather, they provide weaker guarantees about how memory accesses before and after reads and writes may be observed to be ordered with respect to each other. Certain operations such as creating a new thread, entering a lock, or using one of the Interlocked family of methods introduce stronger guarantees about observation of ordering. If you want more details, read sections 3.10 and 10.5.3 of the C# 4.0 specification.

坦率地说,我不鼓励你做一个不稳定的领域.易挥发的字段表明你正在做一些非常疯狂的事情:你是试图在两个不同的线程上读取和写入相同的值不用锁就位.锁保证内存读取或修改里面的锁被观察到是一致的,锁保证一次只有一个线程访问给定的内存块,所以在.锁太慢的情况非常多小,并且您将代码弄错的可能性因为你不明白确切的内存模型非常大.一世除了最琐碎的代码外,不要尝试编写任何低锁代码互锁操作的用法.我将volatile"的用法留给真正的专家.

Frankly, I discourage you from ever making a volatile field. Volatile fields are a sign that you are doing something downright crazy: you're attempting to read and write the same value on two different threads without putting a lock in place. Locks guarantee that memory read or modified inside the lock is observed to be consistent, locks guarantee that only one thread accesses a given chunk of memory at a time, and so on. The number of situations in which a lock is too slow is very small, and the probability that you are going to get the code wrong because you don't understand the exact memory model is very large. I don't attempt to write any low-lock code except for the most trivial usages of Interlocked operations. I leave the usage of "volatile" to real experts.

进一步阅读: