lock español ejemplo book c# multithreading synchronization locking mutex

español - mutex c# ejemplo



¿Cuáles son las diferencias entre varias opciones de sincronización de subprocesamiento en C#? (6)

Como se indica en ECMA, y como se puede observar en los métodos reflejados, la instrucción de bloqueo es básicamente equivalente a

object obj = x; System.Threading.Monitor.Enter(obj); try { … } finally { System.Threading.Monitor.Exit(obj); }

A partir del ejemplo mencionado anteriormente, vemos que los monitores pueden bloquear objetos.

Los de Mutexe son útiles cuando necesita sincronización entre procesos, ya que pueden bloquear un identificador de cadena. El mismo identificador de cadena puede ser utilizado por diferentes procesos para adquirir el bloqueo.

Los semáforos son como mutex en esteroides, permiten el acceso simultáneo al proporcionar un recuento máximo de acceso concurrente ''. Una vez que se alcanza el límite, el semáforo comienza a bloquear cualquier acceso adicional al recurso hasta que una de las personas que llaman libere el semáforo.

¿Alguien puede explicar la diferencia entre:

  • lock (someobject) {}
  • Usando Mutex
  • Usando semáforo
  • Usando el monitor
  • Usar otras clases de sincronización de .Net

Simplemente no puedo resolverlo. Me parece que los dos primeros son lo mismo?


Gran pregunta Tal vez estoy equivocado ... Déjame intentar ... Revisión # 2 de mi respuesta original ... con un poco más de comprensión. Gracias por hacerme leer :)

bloqueo (obj)

  • es una construcción CLR que para la sincronización de subprocesos (intra-objeto?). Asegura que solo un hilo pueda tomar posesión del bloqueo del objeto e ingrese el bloque bloqueado de código. Otros hilos deben esperar hasta que el propietario actual renuncie al bloqueo saliendo del bloque de código. También se recomienda que bloquee un objeto miembro privado de su clase.

Monitores

  • lock (obj) se implementa internamente usando un monitor. Debería preferir el bloqueo (obj) porque evita que se emborrache, como olvidar el procedimiento de limpieza. Es una prueba a prueba de idiotas si lo harás.
    En general, se prefiere usar Monitor en lugar de los mutex, ya que los monitores se diseñaron específicamente para .NET Framework y, por lo tanto, hacen un mejor uso de los recursos.

El uso de un bloqueo o monitor es útil para evitar la ejecución simultánea de bloques de código sensibles a hilos, pero estos constructos no permiten que un hilo comunique un evento a otro. Esto requiere eventos de sincronización , que son objetos que tienen uno de dos estados, señalados y no señalizados, que se pueden usar para activar y suspender hilos. Mutex, semáforos son conceptos de nivel de sistema operativo. Por ejemplo, con un mutex con nombre se puede sincronizar a través de múltiples (administrado) exes (asegurando que solo una instancia de su aplicación se está ejecutando en la máquina).

Mutex:

  • Sin embargo, a diferencia de los monitores, se puede usar un mutex para sincronizar subprocesos entre procesos. Cuando se utiliza para la sincronización entre procesos, un mutex se denomina mutex con nombre porque se va a utilizar en otra aplicación y, por lo tanto, no se puede compartir mediante una variable global o estática. Debe tener un nombre para que ambas aplicaciones puedan acceder al mismo objeto mutex. Por el contrario, la clase Mutex es un contenedor de una construcción Win32. Si bien es más potente que un monitor, un mutex requiere transiciones de interoperabilidad que son más costosas desde el punto de vista informático que las requeridas por la clase Monitor.

Semaphores (duele mi cerebro).

  • Use la clase de semáforo para controlar el acceso a un grupo de recursos. Los subprocesos ingresan al semáforo llamando al método WaitOne, que se hereda de la clase WaitHandle, y liberan el semáforo llamando al método Release. El recuento en un semáforo se reduce cada vez que un subproceso ingresa al semáforo, y se incrementa cuando un subproceso libera el semáforo. Cuando el recuento es cero, las solicitudes subsiguientes se bloquean hasta que otros subprocesos liberen el semáforo. Cuando todos los hilos han liberado el semáforo, el recuento se encuentra en el valor máximo especificado cuando se creó el semáforo. Un hilo puede ingresar al semáforo varias veces ... La clase de semáforo no impone la identidad del hilo en WaitOne o Release ... la responsabilidad de los programadores no es estorbar. Los semáforos son de dos tipos: semáforos locales y semáforos del sistema con nombre . Si crea un objeto de semáforo utilizando un constructor que acepta un nombre, se asocia con un semáforo del sistema operativo de ese nombre. Los semáforos del sistema con nombre son visibles en todo el sistema operativo y se pueden usar para sincronizar las actividades de los procesos. Un semáforo local existe solo dentro de su proceso. Puede ser utilizado por cualquier hilo en su proceso que tenga una referencia al objeto semáforo local. Cada objeto de semáforo es un semáforo local separado.

LA PÁGINA PARA LEER - Sincronización de hilo (C #)


Hice las clases y el soporte de CLR para enhebrar en DotGNU y tengo algunas ideas ...

A menos que requiera bloqueos de procesos cruzados, siempre debe evitar usar Mutex y semáforos. Estas clases en .NET son envoltorios alrededor de Win32 Mutex y Semáforos y son bastante pesadas (requieren un cambio de contexto en Kernel que es caro, especialmente si su bloqueo no está en disputa).

Como se menciona a otros, la sentencia de bloqueo C # es compilador mágico para Monitor.Enter y Monitor.Exit (existente dentro de un try / finally).

Los monitores tienen un mecanismo de espera / señal simple pero potente que los Mutex no tienen a través de los métodos Monitor.Pulse / Monitor.Wait. El equivalente de Win32 sería objetos de evento a través de CreateEvent que en realidad también existen en .NET como WaitHandles. El modelo Pulse / Wait es similar a pthread_signal y pthread_wait de Unix, pero son más rápidos porque pueden ser operaciones completamente en modo usuario en el caso no contencioso.

Monitor.Pulse / Wait es simple de usar. En un hilo, bloqueamos un objeto, revisamos un indicador / estado / propiedad y si no es lo que estamos esperando, llame a Monitor. Espere que suelte el bloqueo y espere hasta que se envíe un pulso. Cuando la espera vuelve, volvemos y revisamos el indicador / estado / propiedad nuevamente. En el otro hilo, bloqueamos el objeto cada vez que cambiamos el indicador / estado / propiedad y luego llamamos PulseAll para activar cualquier hilo que esté escuchando.

A menudo queremos que nuestras clases sean seguras para hilos, por lo que ponemos bloqueos en nuestro código. Sin embargo, a menudo sucede que nuestra clase solo será utilizada por un hilo. Esto significa que los bloqueos ralentizan innecesariamente nuestro código ... aquí es donde las optimizaciones inteligentes en el CLR pueden ayudar a mejorar el rendimiento.

No estoy seguro de la implementación de bloqueos de Microsoft, pero en DotGNU y Mono, un marcador de estado de bloqueo se almacena en el encabezado de cada objeto. Cada objeto en .NET (y Java) puede convertirse en un bloqueo, por lo que cada objeto debe admitir esto en su encabezado. En la implementación de DotGNU, hay un indicador que le permite usar una tabla hash global para cada objeto que se usa como un bloqueo; esto tiene el beneficio de eliminar una sobrecarga de 4 bytes para cada objeto. Esto no es bueno para la memoria (especialmente para sistemas integrados que no están muy roscados) pero tiene un impacto en el rendimiento.

Tanto Mono como DotGNU utilizan efectivamente mutexes para realizar bloqueos / esperas, pero utilizan operaciones de compare-and-exchange tipo spinlock para eliminar la necesidad de realizar realmente bloqueos rígidos a menos que sea realmente necesario:

Puede ver un ejemplo de cómo los monitores se pueden implementar aquí:

http://cvs.savannah.gnu.org/viewvc/dotgnu-pnet/pnet/engine/lib_monitor.c?revision=1.7&view=markup



Re "Uso de otras clases de sincronización .Net": algunas de las otras que debe conocer:

También hay más construcciones de bloqueo (baja sobrecarga) en CCR / TPL (las Extensiones paralelas CTP), pero IIRC, estas estarán disponibles en .NET 4.0


Una advertencia adicional para bloquear cualquier Mutex compartido que haya identificado con una ID de cadena es que tendrá un mutex "Local /" predeterminado y no se compartirá entre sesiones en un entorno de servidor de terminal.

Prefija su identificador de cadena con "Global /" para asegurar que el acceso a los recursos compartidos del sistema esté controlado adecuadamente. Solo me encontré con un montón de problemas sincronizando las comunicaciones con un servicio que se ejecutaba bajo la cuenta SYSTEM antes de darme cuenta de esto.