Volatile 类
定义
重要
一些信息与预发行产品相关,相应产品在发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。
包含用于执行易失性内存操作的方法。
public ref class Volatile abstract sealed
public static class Volatile
type Volatile = class
Public Class Volatile
- 继承
-
Volatile
注解
在多处理器系统上,由于编译器或处理器中的性能优化,当多个处理器在同一内存上运行时,常规内存操作可能会重新排序。 易失性内存操作可防止对操作进行某些类型的重新排序。 易失性写入操作可防止线程上的早期内存操作在易失写入后重新排序。 易失读取操作可防止在易失读取之前重新排序线程上的内存操作。 这些操作可能涉及某些处理器上的内存屏障,这可能会影响性能。
例如,请考虑以下方案,其中包含两个线程和两 Int32 个字段 x , y 并且最初为零:
| 线程 1 | 线程 2 |
|---|---|
x = 1; |
int y2 = Volatile.Read(ref y); |
Volatile.Write(ref y, 1); |
int x2 = x; |
易失性读取和写入可防止对每个线程中的两个操作进行重新排序,例如编译器或处理器。 无论这些操作实际发生在一个线程相对于另一个线程的顺序,即使在多处理器系统上,线程可能在不同的处理器上运行,易失性操作保证线程 2 不会看到 y2 == 1 和 x2 == 0。 在线程 1 上, x 写入必须出现在易失写入之前 y,在线程 2 x 上,读取必须出现在易失读取 y之后。 因此,如果线程 2 看到 y2 == 1,它也必须看到 x2 == 1。
但是,请考虑与上述方案相同的方案,具体顺序会执行操作:
| Sequence | 线程 1 | 线程 2 |
|---|---|---|
| 1 | x = 1; |
... |
| 2 | Volatile.Write(ref y, 1); |
... |
| 3 | ... |
int y2 = Volatile.Read(ref y); |
| 4 | ... |
int x2 = x; |
即使对线程 1 的易失性写入 y 发生在线程 2 的 y 易失读取之前,线程 2 仍可能会看到 y2 == 0。 易失写入 y 不保证对不同处理器进行以下易失读取 y 将看到更新的值。
注释
易失性内存操作适用于同步的特殊情况,其中正常锁定不是可接受的替代方法。 在正常情况下,C# lock 语句、Visual Basic SyncLock 语句和 Monitor 类提供了同步数据访问的最简单、最不容易出错的方法,Lazy<T> 类提供了一种简单的方法来编写延迟初始化代码,而无需直接使用双重检查锁定。
和Volatile.ReadVolatile.Write方法启用语言不支持的功能。 例如:
某些语言(如Visual Basic)无法识别易失性内存操作的概念。 该 Volatile 类提供此类语言的功能。
注释
调用其中一种方法仅影响单个内存访问。 若要为字段提供有效的同步,对字段的所有访问都必须使用 Volatile.Read 和 Volatile.Write。
在 C# 中,对字段使用
volatile修饰符可确保每个对该字段的访问都是易失性内存操作,但volatile修饰符不能应用于数组元素。 这些 Volatile.Read 元素和 Volatile.Write 方法可用于数组元素。
方法
| 名称 | 说明 |
|---|---|
| Read(Boolean) |
读取指定字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。 |
| Read(Byte) |
读取指定字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。 |
| Read(Double) |
读取指定字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。 |
| Read(Int16) |
读取指定字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。 |
| Read(Int32) |
读取指定字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。 |
| Read(Int64) |
读取指定字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。 |
| Read(IntPtr) |
读取指定字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。 |
| Read(SByte) |
读取指定字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。 |
| Read(Single) |
读取指定字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。 |
| Read(UInt16) |
读取指定字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。 |
| Read(UInt32) |
读取指定字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。 |
| Read(UInt64) |
读取指定字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。 |
| Read(UIntPtr) |
读取指定字段的值。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。 |
| Read<T>(T) |
从指定字段读取对象引用。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果读取或写入出现在代码中的此方法之后,处理器无法在此方法之前移动它。 |
| Write(Boolean, Boolean) |
将指定的值写入指定字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。 |
| Write(Byte, Byte) |
将指定的值写入指定字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。 |
| Write(Double, Double) |
将指定的值写入指定字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。 |
| Write(Int16, Int16) |
将指定的值写入指定字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。 |
| Write(Int32, Int32) |
将指定的值写入指定字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。 |
| Write(Int64, Int64) |
将指定的值写入指定字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。 |
| Write(IntPtr, IntPtr) |
将指定的值写入指定字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。 |
| Write(SByte, SByte) |
将指定的值写入指定字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。 |
| Write(Single, Single) |
将指定的值写入指定字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。 |
| Write(UInt16, UInt16) |
将指定的值写入指定字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。 |
| Write(UInt32, UInt32) |
将指定的值写入指定字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。 |
| Write(UInt64, UInt64) |
将指定的值写入指定字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。 |
| Write(UIntPtr, UIntPtr) |
将指定的值写入指定字段。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。 |
| Write<T>(T, T) |
写入对指定字段的指定对象引用。 在需要内存的系统上,插入一个内存屏障,以防止处理器重新排序内存操作,如下所示:如果在代码中出现此方法之前读取或写入,处理器将无法在此方法之后移动它。 |