Volatile Klasa
Definicja
Ważne
Niektóre informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany przed wydaniem. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Zawiera metody wykonywania nietrwałych operacji pamięci.
public ref class Volatile abstract sealed
public static class Volatile
type Volatile = class
Public Class Volatile
- Dziedziczenie
-
Volatile
Uwagi
W systemie wieloprocesorowym ze względu na optymalizacje wydajności w kompilatorze lub procesorze regularne operacje pamięci mogą wydawać się zmieniane, gdy wiele procesorów działa na tej samej pamięci. Nietrwałe operacje pamięci zapobiegają niektórym typom zmiany kolejności w odniesieniu do operacji. Nietrwała operacja zapisu uniemożliwia wcześniejsze operacje pamięci w wątku, które mają być zmieniane po zapisie nietrwałym. Nietrwała operacja odczytu uniemożliwia późniejsze operacje na pamięci w wątku, które mają być zmieniane przed odczytem nietrwałym. Te operacje mogą obejmować bariery pamięci w niektórych procesorach, co może mieć wpływ na wydajność.
Rozważmy na przykład następujący scenariusz z dwoma wątkami i dwoma Int32 polami x , y które początkowo są zerowe:
| Wątek 1 | Wątek 2 |
|---|---|
x = 1; |
int y2 = Volatile.Read(ref y); |
Volatile.Write(ref y, 1); |
int x2 = x; |
Nietrwałe operacje odczytu i zapisu uniemożliwiają zmiana kolejności dwóch operacji w każdym wątku, takich jak kompilator lub procesor. Niezależnie od kolejności, w jakiej te operacje rzeczywiście występują w jednym wątku względem drugiego wątku, nawet w systemie wieloprocesorowym, w którym wątki mogą być uruchamiane na różnych procesorach, operacje lotne gwarantują, że wątek 2 nie będzie widział y2 == 1 i x2 == 0. W wątku 1 zapis x musi pojawić się przed nietrwałym zapisem do y, a w wątku 2 odczyt x musi występować po nietrwałym yodczycie . Więc jeśli wątek 2 widzi y2 == 1, musi również zobaczyć x2 == 1.
Należy jednak wziąć pod uwagę ten sam scenariusz co powyżej z określoną sekwencją, w której występują operacje:
| Sequence | Wątek 1 | Wątek 2 |
|---|---|---|
| 1 | x = 1; |
... |
| 2 | Volatile.Write(ref y, 1); |
... |
| 3 | ... |
int y2 = Volatile.Read(ref y); |
| 4 | ... |
int x2 = x; |
Mimo że nietrwały zapis w y wątku 1 wystąpił przed nietrwałym odczytem y w wątku 2, wątek 2 może nadal widzieć y2 == 0wartość .
y Nie gwarantuje, że na innym procesorze zostanie wyświetlona następująca liczba nietrwałych odczytów y na innym procesorze.
Note
- Nietrwałe odczyty i zapisy zapewniają, że wartość jest odczytywana lub zapisywana w pamięci, a nie buforowana (na przykład w rejestrze procesora). W związku z tym można użyć tych operacji, aby zsynchronizować dostęp do pola, które można zaktualizować za pomocą innego wątku lub sprzętu.
- Klasa Volatile udostępnia również operacje odczytu i zapisu dla niektórych typów 64-bitowych, takich jak Int64 i Double. Nietrwałe operacje odczytu i zapisu w takiej 64-bitowej pamięci są niepodzielne nawet w przypadku procesorów 32-bitowych, w przeciwieństwie do zwykłych operacji odczytu i zapisu.
Nietrwałe operacje pamięci są przeznaczone dla specjalnych przypadków synchronizacji, gdzie normalne blokowanie nie jest akceptowalną alternatywą. W normalnych okolicznościach instrukcja C# lock, instrukcja Visual Basic SyncLock, a klasa Monitor zapewnia najprostszy i najmniej podatny na błędy sposób synchronizowania dostępu do danych, a klasa Lazy<T> zapewnia prosty sposób pisania leniwego kodu inicjowania bez bezpośredniego używania podwójnej blokady.
Metody Volatile.Read i Volatile.Write umożliwiają korzystanie z funkcji, które nie są obsługiwane w językach. Przykład:
Niektóre języki, takie jak Visual Basic, nie rozpoznają koncepcji operacji nietrwałej pamięci. Klasa Volatile udostępnia te funkcje w takich językach.
Note
Wywołanie jednej z tych metod ma wpływ tylko na pojedynczy dostęp do pamięci. Aby zapewnić skuteczną synchronizację dla pola, cały dostęp do pola musi być używany i Volatile.ReadVolatile.Write.
W języku C# użycie
volatilemodyfikatora w polu gwarantuje, że każdy dostęp do tego pola jest operacją nietrwałej pamięci, alevolatilemodyfikator nie może być stosowany do elementów tablicy. Metody Volatile.Read i Volatile.Write mogą być używane w elementach tablicy.
Metody
| Nazwa | Opis |
|---|---|
| Read(Boolean) |
Odczytuje wartość określonego pola. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: jeśli operacja odczytu lub zapisu pojawi się po tej metodzie w kodzie, procesor nie może przenieść go przed tą metodą. |
| Read(Byte) |
Odczytuje wartość określonego pola. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: jeśli operacja odczytu lub zapisu pojawi się po tej metodzie w kodzie, procesor nie może przenieść go przed tą metodą. |
| Read(Double) |
Odczytuje wartość określonego pola. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: jeśli operacja odczytu lub zapisu pojawi się po tej metodzie w kodzie, procesor nie może przenieść go przed tą metodą. |
| Read(Int16) |
Odczytuje wartość określonego pola. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: jeśli operacja odczytu lub zapisu pojawi się po tej metodzie w kodzie, procesor nie może przenieść go przed tą metodą. |
| Read(Int32) |
Odczytuje wartość określonego pola. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: jeśli operacja odczytu lub zapisu pojawi się po tej metodzie w kodzie, procesor nie może przenieść go przed tą metodą. |
| Read(Int64) |
Odczytuje wartość określonego pola. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: jeśli operacja odczytu lub zapisu pojawi się po tej metodzie w kodzie, procesor nie może przenieść go przed tą metodą. |
| Read(IntPtr) |
Odczytuje wartość określonego pola. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: jeśli operacja odczytu lub zapisu pojawi się po tej metodzie w kodzie, procesor nie może przenieść go przed tą metodą. |
| Read(SByte) |
Odczytuje wartość określonego pola. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: jeśli operacja odczytu lub zapisu pojawi się po tej metodzie w kodzie, procesor nie może przenieść go przed tą metodą. |
| Read(Single) |
Odczytuje wartość określonego pola. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: jeśli operacja odczytu lub zapisu pojawi się po tej metodzie w kodzie, procesor nie może przenieść go przed tą metodą. |
| Read(UInt16) |
Odczytuje wartość określonego pola. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: jeśli operacja odczytu lub zapisu pojawi się po tej metodzie w kodzie, procesor nie może przenieść go przed tą metodą. |
| Read(UInt32) |
Odczytuje wartość określonego pola. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: jeśli operacja odczytu lub zapisu pojawi się po tej metodzie w kodzie, procesor nie może przenieść go przed tą metodą. |
| Read(UInt64) |
Odczytuje wartość określonego pola. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: jeśli operacja odczytu lub zapisu pojawi się po tej metodzie w kodzie, procesor nie może przenieść go przed tą metodą. |
| Read(UIntPtr) |
Odczytuje wartość określonego pola. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: jeśli operacja odczytu lub zapisu pojawi się po tej metodzie w kodzie, procesor nie może przenieść go przed tą metodą. |
| Read<T>(T) |
Odczytuje odwołanie do obiektu z określonego pola. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: jeśli operacja odczytu lub zapisu pojawi się po tej metodzie w kodzie, procesor nie może przenieść go przed tą metodą. |
| Write(Boolean, Boolean) |
Zapisuje określoną wartość w określonym polu. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: Jeśli przed tą metodą w kodzie pojawi się odczyt lub zapis, procesor nie może przenieść go po tej metodzie. |
| Write(Byte, Byte) |
Zapisuje określoną wartość w określonym polu. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: Jeśli przed tą metodą w kodzie pojawi się odczyt lub zapis, procesor nie może przenieść go po tej metodzie. |
| Write(Double, Double) |
Zapisuje określoną wartość w określonym polu. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: Jeśli przed tą metodą w kodzie pojawi się odczyt lub zapis, procesor nie może przenieść go po tej metodzie. |
| Write(Int16, Int16) |
Zapisuje określoną wartość w określonym polu. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: Jeśli przed tą metodą w kodzie pojawi się odczyt lub zapis, procesor nie może przenieść go po tej metodzie. |
| Write(Int32, Int32) |
Zapisuje określoną wartość w określonym polu. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: Jeśli przed tą metodą w kodzie pojawi się odczyt lub zapis, procesor nie może przenieść go po tej metodzie. |
| Write(Int64, Int64) |
Zapisuje określoną wartość w określonym polu. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: Jeśli przed tą metodą w kodzie pojawi się odczyt lub zapis, procesor nie może przenieść go po tej metodzie. |
| Write(IntPtr, IntPtr) |
Zapisuje określoną wartość w określonym polu. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: Jeśli przed tą metodą w kodzie pojawi się odczyt lub zapis, procesor nie może przenieść go po tej metodzie. |
| Write(SByte, SByte) |
Zapisuje określoną wartość w określonym polu. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: Jeśli przed tą metodą w kodzie pojawi się odczyt lub zapis, procesor nie może przenieść go po tej metodzie. |
| Write(Single, Single) |
Zapisuje określoną wartość w określonym polu. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: Jeśli przed tą metodą w kodzie pojawi się odczyt lub zapis, procesor nie może przenieść go po tej metodzie. |
| Write(UInt16, UInt16) |
Zapisuje określoną wartość w określonym polu. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: Jeśli przed tą metodą w kodzie pojawi się odczyt lub zapis, procesor nie może przenieść go po tej metodzie. |
| Write(UInt32, UInt32) |
Zapisuje określoną wartość w określonym polu. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: Jeśli przed tą metodą w kodzie pojawi się odczyt lub zapis, procesor nie może przenieść go po tej metodzie. |
| Write(UInt64, UInt64) |
Zapisuje określoną wartość w określonym polu. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: Jeśli przed tą metodą w kodzie pojawi się odczyt lub zapis, procesor nie może przenieść go po tej metodzie. |
| Write(UIntPtr, UIntPtr) |
Zapisuje określoną wartość w określonym polu. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: Jeśli przed tą metodą w kodzie pojawi się odczyt lub zapis, procesor nie może przenieść go po tej metodzie. |
| Write<T>(T, T) |
Zapisuje określone odwołanie do określonego obiektu w określonym polu. W systemach, które tego wymagają, wstawia barierę pamięci, która uniemożliwia procesorowi zmienianie kolejności operacji pamięci w następujący sposób: Jeśli przed tą metodą w kodzie pojawi się odczyt lub zapis, procesor nie może przenieść go po tej metodzie. |