2012-09-14 13 views
19

¿Cuál es la diferencia entre Interlocked.Exchange y Volatile.Write?diferencia entre Interlocked.Exchange y Volatile.Write?

Ambos métodos actualizan el valor de alguna variable. ¿Alguien puede resumir cuándo usar cada uno de ellos?

http://msdn.microsoft.com/ru-ru/library/bb337971 y http://msdn.microsoft.com/en-us/library/gg712713.aspx

En particular, es necesario que actualice el doble punto de mi matriz, y quiero otro hilo para ver el valor más actualizado. ¿Qué se prefiere? Interlocked.Exchange(ref arr[3], myValue) o Volatile.Write(ref arr[3], info); donde arr se declara como double?

============================================== ============================== ejemplo real, declaro doble matriz así:

private double[] _cachedProduct; 

En una hILO actualizo de esa manera:

 _cachedProduct[instrumentId] = calcValue; 
     ... 
     are.Set(); 

En otro hilo leí esta matriz de esa manera:

 while(true) { 
      are.WaitOne(); 
      ... 
       result += _cachedProduct[instrumentId]; 
      ... 
     } 

Para mí solo funciona bien como está. Sin embargo, para asegurarse de que "siempre funcionará", no importa lo que parezca, debo agregar Volatile.Write o Interlocked.Exchange. Debido a que la actualización doble no está garantizada como atómica http://msdn.microsoft.com/en-us/library/aa691278%28VS.71%29.aspx

En la respuesta a esta pregunta, quiero ver una comparación detallada de las clases Volátil e Interbloqueado. ¿Por qué necesitamos 2 clases? ¿Cuál y cuándo usar?

+0

No puede usar Volatile.Write en este caso específico: solo acepta tipos de referencia, no tipos de valores. –

+0

Está utilizando un identificador de espera, ya * garantiza * que el otro subproceso ve el valor más nuevo por completo. * Siempre * funcionará. – harold

Respuesta

11

Interlocked.Exchange utiliza una instrucción de procesador que garantiza una operación atómica.

El Volatile.Write hace lo mismo, pero también incluye una operación de barrera de memoria. Creo que Microsoft agregó Volatile.Write en DotNet 4.5 debido a la compatibilidad de los procesadores ARM en Windows 8. Los procesadores Intel y ARM difieren en el reordenamiento de la operación de la memoria.

En Intel, tiene la garantía de que las operaciones de acceso a la memoria se realizarán en el mismo orden en que se emiten, o al menos que una operación de escritura no se reordene.

De Intel® 64 e IA-32 Arquitecturas de Software Manual del desarrollador, Capítulo 8:

8.2.2 Orden Memoria en P6 y más recientes del procesador Familias El procesador Intel Core 2 Duo, Intel Atom, Intel Core Duo , Los procesadores Pentium 4 y P6 de la familia también usan un modelo de ordenamiento de memoria ordenado por procesador que puede definirse como "escribir ordenado con reenvío de almacenamiento intermedio" Este modelo se puede caracterizar de la siguiente manera.

En ARM no tiene este tipo de garantía, por lo que se requiere una barrera de memoria. Puede encontrar un blog de ARM explicando esto aquí: http://blogs.arm.com/software-enablement/594-memory-access-ordering-part-3-memory-access-ordering-in-the-arm-architecture/

En su ejemplo, como la operación con doble no garantiza que sea atómica, recomendaría un candado para acceder a ella. Recuerde que debe usar el bloqueo en ambas partes de su código, al leer y establecer el valor.

Un ejemplo más completo sería mejor responder a su pregunta, ya que no está claro lo que sucede después de establecer estos valores. Para un vector, si tiene más lectores que escritores, considere el uso de un objeto ReaderWriterLockSlim: http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx

El número de subprocesos y la frecuencia de lectura/escritura pueden cambiar drásticamente su estrategia de bloqueo.

+0

no quiero usar el bloqueo, porque una "actualización doble" de los sistemas x64 es probablemente atómica y no quiero introducir latencia adicional que no es necesaria. este es un código muy sensible al tiempo, así que realmente quiero ganar varios microsegundos adicionales. – javapowered

+0

hm así 'Volatile.Write' garantiza la atomicidad. msdn no dice nada sobre eso. ¿Por qué sugieres usar 'lock'? ¿por qué no usar 'Interlock.Exchage' o' Volatile'? – javapowered

+0

Usé la descripción de la clase Volátil para basar mi respuesta. Un buen artículo sobre la diferencia entre atómico y volátil se puede encontrar aquí: http://blogs.msdn.com/b/ericlippert/archive/2011/05/26/atomicity-volatility-and-immutability-are-different-part -one.aspx? PageIndex = 2 Comprobé la definición de lenguaje C# 4.0. En la sección 5.5, no actualizaron el documento para incluir el doble como una operación atómica. Usted pidió una forma de garantizar que siempre funcionaría, por lo que un bloqueo es una garantía. En el caso específico de su ejemplo, dependerá de qué subproceso incremente el instrumentId – nmenezes