El concepto de bloqueos de lectura-escritura es sencillo, permitiendo que múltiples hilos adquieran bloqueos de lectura al mismo tiempo, pero solo un hilo puede obtener bloqueos de escritura al mismo tiempo, por lo que también se denominan bloqueos exclusivos compartidos. En C#, se recomienda usar la clase ReaderWriterLockSlim para completar la función de bloqueo de lectura/escritura. En algunos casos, el número de lecturas de un objeto es mucho mayor que el número de modificaciones, y si simplemente se bloquea mediante bloqueo, afectará la eficiencia de la lectura. Si se utiliza un bloqueo de lectura-escritura, múltiples hilos pueden leer el objeto al mismo tiempo, y solo será bloqueado cuando el objeto esté ocupado por el bloqueo de escritura. En pocas palabras, cuando un hilo entra en modo lectura, otros hilos aún pueden entrar en modo lectura, suponiendo que un hilo quiera entrar en modo escritura en ese momento, entonces debe ser bloqueado. hasta que el modo de lectura termine. De manera similar, si un hilo entra en modo escritura, los otros hilos serán bloqueados tanto si quieren escribir como leer. Hay 2 formas de entrar en modo escritura/lectura: EnterReadLock intenta entrar en el estado de bloqueo en modo de escritura. TryEnterReadLock(Int32) intenta entrar en el estado de bloqueo en modo lectura, con la opción de seleccionar un tiempo de espera entero. EnterWriteLock intenta entrar en el estado de bloqueo en modo de escritura. TryEnterWriteLock(Int32) intenta entrar en el estado de bloqueo en modo escritura, y se puede seleccionar el tiempo de espera temporal. Hay 2 formas de salir del modo escritura/lectura: ExitReadLock reduce el recuento recursivo del modo de lectura y sale del modo de lectura cuando el recuento resultante es 0 (cero). ExitWriteLock reduce el recuento recursivo del patrón de escritura y sale del modo de escritura cuando el recuento resultante es 0 (cero). Así es como se usa:
Puedes ver que el hilo 3 y el hilo 4 pueden entrar en modo de lectura al mismo tiempo, mientras que el hilo 5 puede entrar en modo de escritura tras 5 segundos (es decir, después de que los hilos 3 y 4 salgan del bloqueo de lectura). Modifica el código anterior, primero abre 2 hilos en modo escritura y luego abre hilos en modo lectura, el código es el siguiente:
Los resultados son los siguientes:
Como puedes ver, el hilo 3 y el hilo 4 entran en modo de escritura, pero el hilo 3 ocupa primero el bloqueo de escritura, así que el hilo 4 tiene que esperar 10 segundos antes de entrar. Los hilos 5 y 6 deben ocupar el bloqueo de lectura, así que espera a que el hilo 4 salga del bloqueo de escritura antes de continuar. TryEnterReadLock y TryEnterWriteLock pueden establecer un tiempo de espera; al ejecutar esta oración, el hilo bloqueará aquí; si el bloqueo puede estar ocupado en ese momento, entonces retornará true, si el tiempo de espera aún no ha ocupado el bloqueo, luego return false, renunciará a la ocupación del bloqueo y continúe ejecutando el siguiente código directamente. EnterUpgradeableReadLock La clase ReaderWriterLockSlim proporciona un modo de lectura actualizable, que se diferencia del modo de lectura en que también puede actualizarse a modo de escritura llamando a los métodos EnterWriteLock o TryEnterWriteLock. Porque solo un hilo puede estar en modo mejorable a la vez. Un hilo que entra en modo mejorable no afectará al hilo en modo de lectura, es decir, cuando un hilo entra en modo mejorable, cualquier número de hilos puede entrar en modo de lectura al mismo tiempo sin bloquear. Si ya hay varios hilos esperando para adquirir un bloqueo de escritura, ejecutar EnterUpgradeableReadLock bloqueará hasta que esos hilos expiren o salgan del bloqueo de escritura. El siguiente código muestra cómo actualizar a un bloqueo de escritura en modo de lectura mejorable.
El impacto de los bloqueos de lectura/escritura en el rendimiento es evidente. El siguiente código de prueba:
El código anterior simula la operación de 500 Tareas, cada una de las cuales ocupa un hilo de pool de hilos, de los cuales 20 son hilos de escritura y 480 hilos de lectura están simulados. Se tarda 10 ms en leer los datos y 100 ms en escribir para probar el método de bloqueo y el método ReaderWriterLockSlim respectivamente. Se puede hacer una estimación, para ReaderWriterLockSlim, asumiendo que 480 hilos leen al mismo tiempo, entonces consume 10 ms, 20 operaciones de escritura ocupan 2000 ms, por lo que el tiempo consumido es de 2010 ms, y para el método de bloqueo ordinario, como todos son exclusivos, 480 operaciones de lectura ocupan 4800ms + 20 operaciones de escritura 2000ms = 6800ms. Los resultados mostraron una mejora notable en el rendimiento.
|