significado significa reservadas que programacion palabras lenguaje identificadores con claves c# multithreading volatile

c# - que - palabras reservadas en programacion y su significado



¿La palabra clave ''volátil'' todavía está rota en C#? (3)

Joe Albahari tiene una gran serie sobre multihebra que es una lectura obligada y que debe conocerse de memoria para cualquier persona que realice subprocesos C #.

En la parte 4, sin embargo, menciona los problemas con la volatilidad:

Tenga en cuenta que aplicar volátil no impide que una escritura seguida de una lectura sea intercambiada, y esto puede crear acertijos. Joe Duffy ilustra bien el problema con el siguiente ejemplo: si Test1 y Test2 se ejecutan simultáneamente en diferentes subprocesos, es posible que ayb terminen con un valor de 0 (a pesar del uso de volátiles tanto en x como en y)

Seguido por una nota de que la documentación de MSDN es incorrecta:

La documentación de MSDN indica que el uso de la palabra clave volátil garantiza que el valor más actualizado esté presente en el campo en todo momento. Esto es incorrecto, ya que como hemos visto, una escritura seguida de una lectura puede reordenarse.

Revisé la documentación de MSDN , que se modificó por última vez en 2015, pero aún contiene una lista:

La palabra clave volátil indica que un campo puede ser modificado por varios hilos que se están ejecutando al mismo tiempo. Los campos que se declaran volátiles no están sujetos a las optimizaciones del compilador que asumen el acceso por un único hilo. Esto asegura que el valor más actualizado esté presente en el campo en todo momento .

En este momento sigo evitando la volatilidad a favor de los hilos más detallados para evitar el uso de datos obsoletos:

private int foo; private object fooLock = new object(); public int Foo { get { lock(fooLock) return foo; } set { lock(fooLock) foo = value; } }

Como las partes sobre multihebra se escribieron en 2011, ¿el argumento sigue siendo válido hoy? ¿Debería evitarse la volatilidad a toda costa a favor de cerraduras o vallas de memoria completa para evitar la introducción de errores muy difíciles de producir que, como se mencionó, incluso dependen del proveedor de la CPU en que se está ejecutando?


Mientras leo la documentación de MSDN, creo que está diciendo que si ves volatilidad en una variable, no tienes que preocuparte por las optimizaciones del compilador que atornillan el valor porque reordenan las operaciones. No dice que esté protegido contra errores causados ​​por su propio código de ejecución de operaciones en hilos separados en el orden incorrecto. (aunque es cierto que el comentario no es claro en cuanto a esto).


volatile es una garantía muy limitada. Significa que la variable no está sujeta a las optimizaciones del compilador que asumen el acceso desde un único hilo. Esto significa que si escribe en una variable de un hilo, luego lo lee de otro hilo, el otro hilo definitivamente tendrá el último valor. Sin volátiles, una máquina multiprocesador sin volátiles, el compilador puede hacer suposiciones sobre el acceso de un solo subproceso, por ejemplo, manteniendo el valor en un registro, lo que impide que otros procesadores tengan acceso al último valor.

Como muestra el ejemplo de código que ha mencionado, no lo protege de tener métodos en diferentes bloques reordenados. En efecto, volatile hace que cada individuo tenga acceso a una variable volatile atómica. No hace ninguna garantía en cuanto a la atomicidad de los grupos de tales accesos.

Si solo quiere asegurarse de que su propiedad tenga un valor único actualizado, debería poder usar solo volatile .

El problema aparece si intenta realizar múltiples operaciones paralelas como si fueran atómicas. Si tiene que forzar varias operaciones para que sean atómicas juntas, debe bloquear toda la operación. Considere el ejemplo nuevamente, pero usando bloqueos:

class DoLocksReallySaveYouHere { int x, y; object xlock = new object(), ylock = new object(); void Test1() // Executed on one thread { lock(xlock) {x = 1;} lock(ylock) {int a = y;} ... } void Test2() // Executed on another thread { lock(ylock) {y = 1;} lock(xlock) {int b = x;} ... } }

La causa de los bloqueos puede causar cierta sincronización, lo que puede impedir que a y b tengan un valor 0 (no lo he probado). Sin embargo, dado que tanto x como y están bloqueados de forma independiente, ya sea a o b pueden terminar de manera no determinista con un valor de 0.

Entonces, en el caso de ajustar la modificación de una sola variable, deberías estar seguro de usar volatile , y realmente no estarías más seguro usando el lock . Si necesita realizar operaciones múltiples de forma atómica, debe usar un lock alrededor de todo el bloque atómico; de lo contrario, la programación aún causará un comportamiento no determinista.


Volátil en su implementación actual no se rompe a pesar de las publicaciones populares de blogs que dicen tal cosa. Sin embargo, está mal especificado y la idea de usar un modificador en un campo para especificar el orden de la memoria no es tan buena (compare la especificación atómica volátil en Java / C # con la de C ++ que tuvo suficiente tiempo para aprender de los errores anteriores). Por otro lado, el artículo de MSDN fue escrito claramente por alguien que no tiene nada que ver con la concurrencia y es completamente falso. La única opción sensata es ignorarlo por completo.

Las garantías volátiles adquieren / liberan la semántica al acceder al campo y solo se pueden aplicar a los tipos que permiten lecturas atómicas y escrituras . No más, no menos. Esto es suficiente para ser útil para implementar muchos algoritmos sin bloqueo de manera eficiente, como los hashmaps sin bloqueo .

Una muestra muy simple es el uso de una variable volátil para publicar datos. Gracias a la volatilidad en x, la afirmación en el siguiente fragmento no puede disparar:

private int a; private volatile bool x; public void Publish() { a = 1; x = true; } public void Read() { if (x) { // if we observe x == true, we will always see the preceding write to a Debug.Assert(a == 1); } }

Volatile no es fácil de usar y en la mayoría de las situaciones es mucho mejor ir con un concepto de nivel superior, pero cuando el rendimiento es importante o está implementando estructuras de datos de bajo nivel, la volatilidad puede ser extremadamente útil.