Es este es un uso correcto de Thread.MemoryBarrier()?
No. Supongamos un hilo establece el indicador antes el bucle incluso comienza a ejecutar. El ciclo aún podría ejecutarse una vez, utilizando un valor en caché de la bandera. ¿Es eso correcto? Ciertamente me parece incorrecto. Me gustaría esperar que si establezco el indicador antes de la primera ejecución del ciclo, el ciclo se ejecute cero veces, no una vez.
Por lo que yo entiendo Thread.MemoryBarrier(), teniendo esta llamada dentro del bucle, mientras que impedirá que mi hilo de trabajo de conseguir una versión en caché de la shouldRun, y prevenir de manera efectiva un bucle infinito suceda. ¿Es correcto mi entendimiento sobre Thread.MemoryBarrier?
La barrera de la memoria se asegurará de que el procesador no hace ningún reordenamientos de lectura y escritura de manera que un acceso a la memoria que es lógicamente antes la barrera es en realidad observa que es después, y vice versa.
Si está empeñado en hacer código de bloqueo bajo, me inclinaría a hacer que el campo sea volátil en lugar de introducir una barrera de memoria explícita. "volátil" es una característica del lenguaje C#. Una característica peligrosa y poco conocida, pero una característica del lenguaje. Comunica claramente al lector del código que el campo en cuestión va a ser utilizado sin bloqueos en múltiples hilos.
¿es esta una manera razonable de garantizar que mi ciclo se detenga una vez que se haya establecido que la ejecución es falsa por algún hilo?
Algunas personas lo consideran razonable. No haría esto en mi propio código sin una razón muy, muy buena.
Por lo general, las técnicas de bloqueo bajo se justifican por consideraciones de rendimiento. Hay dos consideraciones de este tipo:
En primer lugar, un bloqueo disputado es potencialmente extremadamente lento; bloquea siempre que haya código ejecutándose en la cerradura. Si tiene un problema de rendimiento porque hay demasiada contención, primero trataría de resolver el problema eliminando la disputa. Solo si no pudiera eliminar la disputa, ¿usaría una técnica de bloqueo bajo?
En segundo lugar, podría ser que un bloqueo no previsto sea demasiado lento. Si el "trabajo" que está haciendo en el ciclo lleva, digamos, menos de 200 nanosegundos, entonces el tiempo requerido para verificar el bloqueo no previsto -alrededor de 20 ns- es una fracción significativa del tiempo dedicado a hacer el trabajo. En ese caso, le sugiero que haga más trabajo por ciclo. ¿Es realmente necesario que el ciclo se detenga dentro de 200 ns de la bandera de control que se está configurando?
Solo en los escenarios de rendimiento más extremos imagino que el costo de verificar un bloqueo no previsto es una fracción significativa del tiempo que se pasa en el programa.
Y también, por supuesto, si está induciendo una barrera de memoria cada 200 ns o más, también es posible que arruine el rendimiento de otras maneras. El procesador quiere para realizar esas optimizaciones de acceso-memoria-memoria-en-tiempo para usted; si lo obligas a abandonar constantemente esas optimizaciones, te estás perdiendo una posible victoria.
¿No declarar el booleano como Do Volátil ¿la misma cosa? No estoy seguro de Thread.MemoryBarrier por lo tanto, comentar no responder. p.ej. http://www.albahari.com/threading/part4.aspxAnother> "una forma más avanzada de resolver este problema es aplicar la palabra clave volátil al campo _completa. La palabra clave volátil instruye al compilador a generar una valla de adquisición en cada lea de ese campo, y una valla de liberación en cada escritura en ese campo ". Atentamente, –
Volátil es algo muy malo y no debe usarse: http://blogs.msdn.com/b/ericlippert/archive/2011/06/16/atomicity-volatility-and-immutability-are-different-part -three.aspx – Steven
¡Lol, no era consciente de eso! Como programador ex C/ASM, pensé que era algo bueno :) Gracias por el enlace, voy a echar un vistazo. –