Volatile 類別
定義
重要
部分資訊涉及發行前產品,在發行之前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
包含執行揮發性記憶體操作的方法。
public ref class Volatile abstract sealed
public static class Volatile
type Volatile = class
Public Class Volatile
- 繼承
-
Volatile
備註
在多處理器系統中,由於編譯器或處理器的效能優化,當多個處理器同時運作於同一記憶體時,正常的記憶體操作可能會被重新排序。 揮發性記憶體操作會阻止某些類型的重新排序。 揮發性寫入操作防止先前執行緒的記憶體操作被重新排序,使其在揮發性寫入之後發生。 揮發性讀取操作可防止執行緒後續的記憶體操作被重新排序,使其在揮發性讀取之前發生。 這些操作可能涉及某些處理器的記憶體障礙,進而影響效能。
例如,考慮以下情境,兩執行緒及兩個Int32初始為零的欄位yx:
| 執行緒 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; |
即使執行緒 1 上的揮發性寫入 y 發生在執行緒 2 的 y 揮發性讀取之前,執行緒 2 仍可能看到 y2 == 0。 揮發性寫入 y 並不保證在其他處理器上進行的揮發性讀取 y 會看到更新後的值。
Note
揮發性記憶體操作適用於特殊同步情況,當一般鎖定無法作為可接受的替代方案時。 在正常情況下,C# lock 陳述式、Visual Basic SyncLock 陳述式,以及 Monitor 類別,提供了最簡單且最不易出錯的資料存取方式,而 Lazy<T> 類別則提供了一種簡單的方式,可以撰寫懶惰初始化程式碼,而無需直接使用雙重檢查鎖定。
Volatile.Read與Volatile.Write方法啟用了語言中不支援的功能。 例如:
有些語言,如 Visual Basic,並不承認揮發性記憶體操作的概念。 這個 Volatile 類別在這類語言中提供了這些功能。
Note
呼叫其中一種方法只會影響一次記憶體存取。 為了有效同步欄位,所有存取該欄位的存取必須使用 Volatile.Read 和 Volatile.Write。
在 C# 中,對欄位使用
volatile修飾符可保證每次存取該欄位都是揮失性記憶體操作,但volatile修飾符無法套用於陣列元素。 Volatile.Read和Volatile.Write方法可用於陣列元素。
方法
| 名稱 | Description |
|---|---|
| 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) |
將指定的物件參考寫入指定的欄位。 在需要此方法的系統中,會插入一個記憶體屏障,阻止處理器重新排序記憶體操作如下:若讀取或寫入出現在此方法之前,處理器無法在此方法後移動該操作。 |