2012-03-30 6 views
16

recientemente he visto este código en un sitio web, y mi pregunta es la siguiente:Bloqueando una sola variable bool cuando multihilo?

 private bool mbTestFinished = false; 

     private bool IsFinished() 
     { 
      lock(mLock) 
      { 
       return mbTestFinished; 
      } 
     } 

     internal void SetFinished() 
     { 
      lock(mLock) 
      { 
       mbTestFinished = true; 
      } 
     } 

En un entorno multi-hilo, que es realmente necesario para bloquear el acceso al mbTestFinished?

+6

Es el mecanismo más comprobable para garantizar que no sea una lectura en caché de CPU (que no funcionaría bien entre subprocesos) - 'volátil' también funcionaría, pero por razones demasiado complejas (este no es el * intención * de 'volátil', sino más bien: un efecto secundario) –

+4

@MarcGravell Siempre he pensado que _was_ la intención de' volátil'; ¿Hay alguna posibilidad de que arrojes un buen enlace que explique qué es? –

+1

@romkyns: Esta [respuesta] (http://stackoverflow.com/a/4103879/158779) proporciona algunas ideas. –

Respuesta

9

Sí, es necesario. El entorno .Net utiliza algunas optimizaciones y, a veces, si se accede a una ubicación de memoria con frecuencia, los datos se transfieren a los registros de la CPU. Entonces, en este caso, si mbTestFinished está en un registro de CPU, entonces un hilo que lo lea puede tener un valor incorrecto. Por lo tanto, el uso de la clave volátil garantiza que todos los accesos a esta variable se realicen en la ubicación de la memoria, no en los registros. Por otro lado, no tengo idea de la frecuencia de esta ocurrencia. Esto puede ocurrir a una frecuencia muy baja.

9

En mi opinión, no, la cerradura está de más aquí, por dos razones:

  1. variables booleanas no pueden causar lagrimeo asignación como long por ejemplo, por lo tanto, el bloqueo no es necesario.
  2. Para resolver el problema de visibilidad volatile es suficiente. Es cierto que el lock introduce una valla implícita, pero como el lock no es necesario para la atomicidad, es suficiente con volatile.
+0

Esto es cierto suponiendo que el código que se muestra es el elemento * solo * que usa el candado. Si hay otros lugares donde 'mLock' se toma, la conversión a' volátil' podría romper cosas. –

+0

@romkyns: Sí, supongo que es un escenario autocontenido. – Tudor

4

Si mlock es SOLO para la variable mbTestFinished, entonces es un poco de una exageración. En su lugar, puede usar volátil o Interbloqueado, porque ambos son Construcciones en modo de usuario para la sincronización de subprocesos. bloquear (o Monitor de) es un híbrido Construct, en el sentido de que está bien optimizado para evitar que transitan desde/hasta el modo de núcleo siempre que sea posible. El libro "CLR a través de C#" tiene una discusión en profundidad de estos conceptos.