Volatile 類別

定義

包含執行揮發性記憶體操作的方法。

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 == 1x2 == 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

  • 揮發性讀寫確保值被讀寫到記憶體,而非快取(例如在處理器暫存器中)。 因此,你可以利用這些操作同步存取一個欄位,讓其他執行緒或硬體都能更新。
  • Volatile 類別也提供某些 64 位元型態(如 Int64Double)的讀寫操作。 在這種 64 位元記憶體上的揮發性讀寫即使在 32 位元處理器上也是原子性的,這與一般的讀寫不同。

揮發性記憶體操作適用於特殊同步情況,當一般鎖定無法作為可接受的替代方案時。 在正常情況下,C# lock 陳述式、Visual Basic SyncLock 陳述式,以及 Monitor 類別,提供了最簡單且最不易出錯的資料存取方式,而 Lazy<T> 類別則提供了一種簡單的方式,可以撰寫懶惰初始化程式碼,而無需直接使用雙重檢查鎖定。

Volatile.ReadVolatile.Write方法啟用了語言中不支援的功能。 例如:

  • 有些語言,如 Visual Basic,並不承認揮發性記憶體操作的概念。 這個 Volatile 類別在這類語言中提供了這些功能。

    Note

    呼叫其中一種方法只會影響一次記憶體存取。 為了有效同步欄位,所有存取該欄位的存取必須使用 Volatile.ReadVolatile.Write

  • 在 C# 中,對欄位使用 volatile 修飾符可保證每次存取該欄位都是揮失性記憶體操作,但 volatile 修飾符無法套用於陣列元素。 Volatile.ReadVolatile.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)

將指定的物件參考寫入指定的欄位。 在需要此方法的系統中,會插入一個記憶體屏障,阻止處理器重新排序記憶體操作如下:若讀取或寫入出現在此方法之前,處理器無法在此方法後移動該操作。

適用於

另請參閱