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
。
不過,請考慮與上述案例相同的案例,其中包含發生作業的特定順序:
順序 | 執行緒 1 | 執行緒 2 |
---|---|---|
1 | x = 1; |
... |
2 | Volatile.Write(ref y, 1); |
... |
3 | ... |
int y2 = Volatile.Read(ref y); |
4 | ... |
int x2 = x; |
即使線上程 2 上的變動性讀取之前發生對 執行緒 1 的動態寫入 y
y
,執行緒 2 仍會看到 y2 == 0
。 的變動性寫入 y
不保證不同處理器上的下列動態讀取 y
將會看到更新的值。
注意
變動性記憶體作業適用于特殊同步處理案例,其中一般鎖定不是可接受的替代方案。 在一般情況下,C# lock
語句、Visual Basic SyncLock
語句和 Monitor 類別提供最簡單且最容易錯誤的方式來同步處理資料的存取,而 Lazy<T> 類別提供簡單的方式來撰寫延遲初始化程式碼,而不需直接使用雙檢查鎖定。
Volatile.Read和 Volatile.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) |
將指定的物件參考寫入指定的欄位。 在需要它的系統上,以如下方式插入可防止處理器重新排序記憶體作業的記憶體屏障:如果程式碼中這個方法之前出現讀取或寫入,處理器便無法在這個方法之後移動它。 |