对于C#中的volatile字段,实际上可以保证什么?

对于volatile关键字与System.Threading.Thread.VolatileRead / VolatileWriteSystem.Threading.Volatile.Read/Write而言,我对.NET / C#文档感到困惑。我试图了解对于可变字段到底能保证什么,以及这些方法到底在做什么。

我以为volatile提供了发布/获取的语义,但是Thread.VolatileRead / VolatileWrite的文档让我怀疑我的理解是否正确。

这是volatile的语言参考:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/volatile

添加volatile修饰符可确保所有线程均遵守 任何其他线程按以下顺序执行易失性写入: 他们被执行了。不能保证单个总订购 从执行的所有线程来看,都是易失性写入。

到目前为止,这是有道理的。这是语言规范:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/classes#volatile-fields

对于易失性字段,此类重新排序优化受到限制:

对易失性字段的读取称为易失性读取。易失性读取具有“获取语义”。也就是说,可以保证它先于 指令后出现的任何对内存的引用 顺序。 易失性字段的写入称为易失性写入。易失性写入具有“释放语义”。也就是说,它一定会发生 在写指令之前的任何内存引用之后 指令顺序。

这些限制确保所有线程都将观察到不稳定 由任何其他线程执行的写入顺序 执行。不需要遵循实施即可提供 从所有线程的易失性写入的单个总顺序 执行。

同样,volatile似乎提供了发布/获取语义。

但是,然后我看一下Thread.VolatileRead的文档: https://docs.microsoft.com/en-us/dotnet/api/system.threading.thread.volatileread?view=netframework-4.8#System_Threading_Thread_VolatileRead_System_Int64__

读取字段的值。该值是任何人写的最新值 计算机中的处理器,无论处理器数量或 处理器缓存的状态。 ...在多处理器系统上,VolatileRead 获取由任何人写入存储位置的最新值 处理器。这可能需要刷新处理器缓存。

对于Thread.VolatileWrite:

立即将一个值写入字段,以便该值对 计算机中的所有处理器。

这看起来比单个存储/装入栅栏(发布/获取)要严格,尤其是有关刷新处理器缓存的部分,即比volatile更严格的保证。但随后同一文档说:

在C#中,对字段使用volatile修饰符可确保所有 使用VolatileRead或VolatileWrite

访问该字段

所以我的问题是-与存储缓冲区有关的volatile字段可以保证什么-只是释放/获取,还是更强大的Thread.VolatileRead / Write保证?还是我对VolatileRead/Write的理解是错误的,而这些理解与volatile相同?

sgmk3738 回答:对于C#中的volatile字段,实际上可以保证什么?

  1. System.Threading.Thread.VolatileRead/VolatileWriteSystem.Threading.Volatile.Read/Write之间没有区别-这些是相同的辅助方法,它们在读取或写入之前模拟了完整的内存屏障(不必使用MFENCE指令)。这是内部实现:
public static void VolatileWrite(ref sbyte address,sbyte value)
{
  Thread.MemoryBarrier();
  address = value;
}
  1. volatile变量在具有较弱内存模型的过时IA处理器体系结构(Itanium)上使用(-ed)获取/释放语义。

  2. 在最流行的x86架构中,volatile修饰符可避免编译器优化,并且还可使用带有lock前缀的指令来保证一致性。

总而言之,编译器可能会使用各种技巧来遵守C# memory model,其中指出:

  1. volatile 读取之前或在 volatile 写入
  2. 之后,不能进行任何读取或写入。
  3. 所有写入均具有 volatile 写入
  4. 的效果
本文链接:https://www.f2er.com/2774248.html

大家都在问