Nota
L'accés a aquesta pàgina requereix autorització. Pots provar d'iniciar sessió o canviar de directori.
L'accés a aquesta pàgina requereix autorització. Pots provar de canviar directoris.
Use la volatile palabra clave para indicar que varios subprocesos que se ejecutan al mismo tiempo pueden modificar un campo. Por motivos de rendimiento, el compilador, el sistema en tiempo de ejecución e incluso el hardware podrían reorganizar las lecturas y escrituras en ubicaciones de memoria. Declarar un campo como volatile lo excluye de determinados tipos de optimizaciones. No hay ninguna garantía de una única ordenación total de escrituras volátiles como se ve en todos los subprocesos de ejecución. Para obtener más información, vea la clase Volatile.
Precaución
La volatile palabra clave a menudo se malinterpreta y se usa incorrectamente en la programación multiproceso. En la mayoría de los escenarios, use alternativas más seguras y confiables en lugar de volatile. .NET moderno proporciona mejores herramientas de simultaneidad, como la Interlocked clase, la lock instrucción o primitivos de sincronización de nivel superior. Estas alternativas proporcionan una semántica más clara y garantías más sólidas que volatile. Considere la posibilidad de usar volatile solo en escenarios poco frecuentes y avanzados en los que comprende completamente sus limitaciones y ha comprobado que es la solución adecuada.
Nota:
En un sistema multiprocesador, una operación de lectura volátil no garantiza obtener el valor más reciente escrito en esa ubicación de memoria por cualquier procesador. De forma similar, una operación de escritura volátil no garantiza que el valor escrito sea visible inmediatamente para otros procesadores.
La documentación de referencia del lenguaje C# cubre la versión más reciente publicada del lenguaje C#. También contiene documentación inicial sobre las características de las versiones preliminares públicas de la próxima versión del lenguaje.
La documentación identifica cualquier característica introducida por primera vez en las últimas tres versiones del idioma o en las versiones preliminares públicas actuales.
Sugerencia
Para buscar cuándo se introdujo por primera vez una característica en C#, consulte el artículo sobre el historial de versiones del lenguaje C#.
Aplique la volatile palabra clave a los campos de estos tipos:
- Tipos de referencia.
- Tipos de puntero (en un contexto no seguro). Aunque el propio puntero puede ser volátil, el objeto al que apunta no puede ser. En otras palabras, no se puede declarar un "puntero a volátil".
- Tipos simples como
sbyte, ,byte,shortushort,intuint, ,charfloaty .bool - Tipo
enumcon uno de los siguientes tipos base:byte,sbyte,short,ushort,intouint. - Parámetros de tipo genérico conocidos como tipos de referencia.
- IntPtr y UIntPtr.
No se pueden marcar otros tipos, incluidos double y long, como volatile porque no se puede garantizar que las lecturas y escrituras en campos de esos tipos sean atómicas. Para proteger el acceso multiproceso a esos tipos de campos, use los miembros de clase o proteja el Interlocked acceso mediante la lock instrucción .
Para la mayoría de los escenarios multiproceso, incluso con tipos admitidos, prefiere usar operaciones Interlocked, instrucciones lock u otros primitivos de sincronización en lugar de volatile. Estas alternativas son menos propensas a errores de simultaneidad sutiles.
Solo puede aplicar la volatile palabra clave a los campos de o structclass . No se pueden declarar variables locales como volatile.
Alternativas a la volatilidad
En la mayoría de los casos, use una de estas alternativas más seguras en lugar de volatile:
-
Operaciones Interlocked: Proporciona operaciones atómicas para tipos numéricos y asignaciones de referencia. Estas operaciones suelen ser más rápidas y proporcionan garantías más sólidas que
volatile. -
Instrucción
lock: proporciona exclusión mutua y barreras de memoria. Úselo para proteger secciones críticas más grandes. -
Volatile clase: proporciona operaciones explícitas de lectura y escritura volátiles con semántica más clara que la
volatilepalabra clave . - Primitivos de sincronización de nivel superior: como ReaderWriterLockSlim, Semaphoreo colecciones simultáneas de System.Collections.Concurrent.
La volatile palabra clave no proporciona atomicidad para las operaciones distintas de la asignación. No impide las condiciones de carrera y no proporciona garantías de ordenación para otras operaciones de memoria. Estas limitaciones hacen que no sea adecuado para la mayoría de los escenarios de simultaneidad.
En el ejemplo siguiente se muestra cómo declarar una variable de campo pública como volatile.
class VolatileTest
{
public volatile int sharedStorage;
public void Test(int i)
{
sharedStorage = i;
}
}
En el ejemplo siguiente se muestra cómo se puede crear un subproceso auxiliar o de trabajo y usarse para realizar el procesamiento en paralelo con el del subproceso principal. Para obtener más información sobre multithreading, consulte Managed Threading.
public class Worker
{
// This method is called when the thread is started.
public void DoWork()
{
bool work = false;
while (!_shouldStop)
{
work = !work; // simulate some work
}
Console.WriteLine("Worker thread: terminating gracefully.");
}
public void RequestStop()
{
_shouldStop = true;
}
// Keyword volatile is used as a hint to the compiler that this data
// member is accessed by multiple threads.
private volatile bool _shouldStop;
}
public class WorkerThreadExample
{
public static void Main()
{
// Create the worker thread object. This does not start the thread.
Worker workerObject = new Worker();
Thread workerThread = new Thread(workerObject.DoWork);
// Start the worker thread.
workerThread.Start();
Console.WriteLine("Main thread: starting worker thread...");
// Loop until the worker thread activates.
while (!workerThread.IsAlive)
;
// Put the main thread to sleep for 500 milliseconds to
// allow the worker thread to do some work.
Thread.Sleep(500);
// Request that the worker thread stop itself.
workerObject.RequestStop();
// Use the Thread.Join method to block the current thread
// until the object's thread terminates.
workerThread.Join();
Console.WriteLine("Main thread: worker thread has terminated.");
}
// Sample output:
// Main thread: starting worker thread...
// Worker thread: terminating gracefully.
// Main thread: worker thread has terminated.
}
Al agregar el volatile modificador a la declaración de _shouldStop, siempre obtendrá los mismos resultados (similar al extracto que se muestra en el código anterior). Sin embargo, sin ese modificador en el _shouldStop miembro, el comportamiento es impredecible. El DoWork método podría optimizar el acceso de los miembros, lo que da lugar a la lectura de datos obsoletos. Debido a la naturaleza de la programación multiproceso, el número de lecturas obsoletas es impredecible. Diferentes ejecuciones del programa producen resultados algo diferentes.
Especificación del lenguaje C#
Para obtener más información, consulte la Especificación del lenguaje C#. La especificación del lenguaje es el origen definitivo de la sintaxis y el uso de C#.