Bloqueo de C #, monitor, notas de estudio de Mutex

Subproceso: Un subproceso es una unidad de ejecución independiente de un proceso.Cada proceso tiene un subproceso principal, excepto el subproceso principal, que puede contener otros subprocesos.

La importancia del subproceso múltiple: el subproceso múltiple ayuda a mejorar la capacidad de respuesta general del programa y aumenta la eficiencia de la CPU.

Los dominios de aplicaciones de subprocesos múltiples son bastante inestables, porque varios subprocesos pueden ejecutar módulos funcionales compartidos al mismo tiempo. Para evitar que los recursos de la aplicación sean destruidos, se proporcionan tres mecanismos de bloqueo para programas multiproceso, a saber: clase de monitor, palabra clave de bloqueo y clase de mutex.

1. bloqueo

La función implementada por el bloqueo es: el hilo que ingresa más tarde no interrumpirá el hilo actual, sino que esperará el final del hilo actual para continuar la ejecución.

solicitud:

 private Object thisLock=new object();
   lock(thisLock){
               //锁定的代码块
    }

Nota: Evite bloquear el tipo público, de lo contrario, la instancia estará más allá del control del código.

Las estructuras comunes lock (this), lock (typeof (MyType)) y lock ("myLock")
violan esta directriz: si la instancia es de acceso público, se producirá el problema de bloqueo (this).
Si MyType es de acceso público, se producirá un problema de bloqueo (typeof (MyType)).
Dado que cualquier otro código del proceso que utilice la misma cadena compartirá el mismo bloqueo, se produce el problema de bloqueo ("myLock").
La mejor práctica es definir objetos privados para bloquear o variables de objetos estáticos privados para proteger los datos compartidos por todas las instancias.
El siguiente ejemplo ilustra la aplicación del bloqueo: En el
siguiente ejemplo, se crean 5 subprocesos secundarios y las tareas completadas por los subprocesos secundarios son: generar el código del subproceso, retrasar 1 segundo y luego generar el tiempo

Ejemplo:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication5 {
    class Program {
        static void Main(string[] args) {
        Console.WriteLine ("程序开始时间:"+DateTime.Now .ToString());
        Example ex=new Example ();
        Thread []threads=new  Thread[5];
        for (int i=0;i<5;i++)
        {
        threads[i]=new Thread (new ThreadStart(ex.OutPut));
        threads[i].Name =string.Format ("Worker thread#{0}",i) ;
        }
        foreach(Thread t in threads){
        t.Start();
        }
        Console.WriteLine("主线程最后一句代码!"+DateTime.Now.ToString());
        }
    }
    class Example{
    private static object  thisLock=new object ();
    public void OutPut()
    {    
    lock(thisLock){
    Console .WriteLine("->{0}",Thread.CurrentThread.Name);
    Thread.Sleep(1000);
    Console.WriteLine(DateTime.Now);
    }
    }
    
    }
}

Los resultados experimentales son los siguientes:

           Figura 1: Agregar candado

      Figura 2: Sin bloqueo    

Se puede ver en los resultados experimentales que después de agregar el bloqueo, el programa solo puede ejecutar un hilo a la vez. Solo cuando se ejecuta el hilo actual, el siguiente hilo se ejecutará sin bloqueo. La ejecución del programa es caótica y fácil de bloquear.

2. Supervisar

El bloqueo es una encapsulación de Enter y Exit del Monitor, por lo que la combinación de los métodos Enter () y Exit () de la clase Monitor se puede reemplazar por la palabra clave lock.

Además de la función de bloqueo, la clase Monitor también tiene las siguientes funciones:

TryEnter () resuelve el problema de la muerte a largo plazo. Si ocurre una simultaneidad con frecuencia y dura mucho tiempo, el uso de TryEnter puede prevenir eficazmente el estancamiento o la espera prolongada.    

Wait () libera el bloqueo del objeto para permitir que otros subprocesos bloqueen y accedan al objeto. Cuando otros subprocesos acceden al objeto, el subproceso que realiza la llamada esperará. Las señales de pulso se utilizan para notificar a los hilos en espera de cambios en el estado de los objetos.

Pulse (), PulseAll () envían señales a uno o más hilos en espera. Esta señal informa al hilo en espera de que el estado del objeto bloqueado ha cambiado y que el propietario del bloqueo está listo para liberarlo. El hilo en espera se coloca en la cola lista del objeto para que finalmente pueda recibir el bloqueo del objeto. Una vez que el hilo tiene el bloqueo, puede verificar el nuevo estado del objeto para ver si ha alcanzado el estado deseado.

Nota: Los métodos Pulse, PulseAll y Wait deben llamarse desde dentro de un bloque de código sincronizado.

3. Mutex (mutex)

La característica sobresaliente de Mutex es que puede realizar un acceso exclusivo a los recursos a través de los límites del dominio de la aplicación, es decir, puede usarse para sincronizar subprocesos en diferentes procesos, esta función es a expensas de más recursos del sistema.    

Mutex y el objeto de evento EventWaitHandler pertenecen al objeto del kernel. El objeto del kernel se usa para la sincronización de subprocesos. El subproceso debe cambiar entre el modo de usuario y el modo de kernel, por lo que la eficiencia es generalmente muy baja. Sin embargo, el uso de objetos de evento y objetos mutuamente excluyentes, como objetos de kernel, Es posible sincronizar entre subprocesos en múltiples procesos.

El mutex Mutex es similar a una batuta. El hilo que recibe la batuta puede comenzar a ejecutarse. Por supuesto, la batuta pertenece a solo un hilo a la vez (Thread Affinity). Si este hilo no libera la batuta (Mutex.ReleaseMutex), entonces todas las demás cosas que necesitan la batuta para funcionar El hilo solo puede esperar a ver la emoción.


Supongo que te gusta

Origin blog.csdn.net/youarenotme/article/details/77877882
Recomendado
Clasificación