Aquí hay numerosas preguntas. Considerándolos uno a la vez:
La asignación de referencia es atómica, entonces, ¿por qué se necesita Interlocked.Exchange (ref Object, Object)?
La asignación de referencia es atómica. Interlocked.Exchange no solo hace referencia a la asignación. Hace una lectura del valor actual de una variable, oculta el valor anterior y asigna el nuevo valor a la variable, todo como una operación atómica.
mi colega dijo que en algunas plataformas no se garantiza que la asignación de referencias sea atómica. ¿Tenía razón mi colega?
No. Se garantiza que la asignación de referencia será atómica en todas las plataformas .NET.
Mi colega está razonando desde premisas falsas. ¿Significa eso que sus conclusiones son incorrectas?
No necesariamente. Su colega podría estar dándole buenos consejos por malas razones. Quizás haya alguna otra razón por la que debería utilizar Interlocked.Exchange. La programación sin candados es increíblemente difícil y en el momento en que se aparta de las prácticas bien establecidas defendidas por los expertos en el campo, se pierde en la maleza y se arriesga a las peores condiciones de carrera. No soy un experto en este campo ni un experto en su código, por lo que no puedo emitir un juicio de una forma u otra.
produce una advertencia "una referencia a un campo volátil no se tratará como volátil" ¿Qué debo pensar al respecto?
Debe comprender por qué esto es un problema en general. Eso conducirá a comprender por qué la advertencia no es importante en este caso particular.
La razón por la que el compilador da esta advertencia es porque marcar un campo como volátil significa "este campo se actualizará en varios subprocesos; no genere ningún código que almacene en caché los valores de este campo y asegúrese de que las lecturas o escrituras de este campo no se "mueve hacia adelante y hacia atrás en el tiempo" a través de inconsistencias de caché del procesador ".
(Supongo que ya comprende todo eso. Si no tiene una comprensión detallada del significado de volátil y cómo afecta la semántica de la caché del procesador, entonces no comprende cómo funciona y no debería usar volátil. Programas sin bloqueo son muy difíciles de hacer bien; asegúrese de que su programa sea correcto porque comprende cómo funciona, no por accidente).
Ahora suponga que crea una variable que es un alias de un campo volátil pasando una referencia a ese campo. Dentro del método llamado, el compilador no tiene ningún motivo para saber que la referencia debe tener semántica volátil. El compilador generará alegremente código para el método que no implementa las reglas para los campos volátiles, pero la variable es un campo volátil. Eso puede arruinar completamente su lógica libre de bloqueos; siempre se asume que siempre se accede a un campo volátil con semántica volátil. No tiene sentido tratarlo como volátil algunas veces y otras no; tiene que ser siempre coherente, de lo contrario no puede garantizar la coherencia en otros accesos.
Por lo tanto, el compilador le advierte cuando hace esto, porque probablemente va a estropear por completo su lógica sin bloqueos cuidadosamente desarrollada.
Por supuesto, Interlocked.Exchange está escrito para esperar un campo volátil y hacer lo correcto. Por tanto, la advertencia es engañosa. Lo lamento mucho; lo que deberíamos haber hecho es implementar algún mecanismo mediante el cual un autor de un método como Interlocked.Exchange podría poner un atributo en el método diciendo "este método que toma una referencia aplica la semántica volátil en la variable, así que suprime la advertencia". Quizás en una versión futura del compilador lo hagamos.
var myresult = await Task.Factory.CreateNew(() => MyWork(exclusivelyLocalStuffOrValueTypeOrCopy));
.O su colega se equivoca o sabe algo que la especificación del lenguaje C # no sabe.
5.5 Atomicidad de referencias variables :
Por lo tanto, puede escribir en la referencia volátil sin riesgo de obtener un valor dañado.
Por supuesto, debe tener cuidado con la forma en que decide qué hilo debe buscar los nuevos datos, para minimizar el riesgo de que más de un hilo a la vez lo haga.
fuente
Interbloqueado Intercambio <T>
Cambia y devuelve el valor original, es inútil porque solo quieres cambiarlo y, como dijo Guffa, ya es atómico.
A menos que un generador de perfiles haya demostrado que es un cuello de botella en su aplicación, debe considerar deshacer los bloqueos, es más fácil de entender y demostrar que su código es correcto.
fuente
Iterlocked.Exchange()
no es solo atómico, también se ocupa de la visibilidad de la memoria:Problemas de sincronización y multiprocesador
Esto significa que además de la atomicidad asegura que:
fuente