Conceptos básicos:
* Exclusión mutua: Un bloqueo asegura que solo un hilo pueda sostener el bloqueo a la vez. Cualquier otro hilo que intente adquirir la cerradura se bloqueará hasta que se libere la cerradura. Esto garantiza la exclusión mutua:solo un hilo puede acceder a la sección crítica (el código protegido por el bloqueo) a la vez.
* Adquiriendo el bloqueo: Antes de acceder a un recurso compartido, un hilo debe adquirir (u obtener) el bloqueo.
* Liberando el bloqueo: Después de acceder al recurso compartido, el hilo debe liberar (o desbloquear) el bloqueo, permitiendo que otros hilos accedan a él.
* Deadlocks: Un punto muerto ocurre cuando dos o más hilos están bloqueados indefinidamente, esperando el uno al otro para liberar las cerraduras que necesitan. El diseño cuidadoso y el pedido de la adquisición de bloqueos son cruciales para evitar los puntos de punto.
Ejemplo (Python conceptual):
`` `Python
Importación de hilo
shared_resource =0
bloquear =threading.lock ()
def increment_resource ():
Global Shared_Resource
Lock.acquire () # adquirir el bloqueo
intentar:
shared_resource +=1
finalmente:
Lock.Release () # libera el bloqueo, incluso si ocurren excepciones
Hilos =[]
para i en el rango (10):
Thread =Threading.Thread (Target =increment_resource)
Threads.append (hilo)
Thread.Start ()
Para hilo en hilos:
Thread.Join ()
print (f "valor final de shared_resource:{shared_resource}") # debería ser 10
`` `` ``
En este ejemplo:
* `Threading.lock ()` Crea un objeto de bloqueo.
* `Lock.Acquire ()` intenta adquirir la cerradura. Si otro hilo contiene el bloqueo, esta llamada se bloqueará hasta que se libere el bloqueo.
* `Lock.Release ()` libera el bloqueo. El bloque `intente ... finalmente` asegura que el bloqueo siempre se libere, incluso si se produce una excepción dentro de la función 'increment_resource`.
Tipos de bloqueos (variaciones):
* Locks recursivos (cerraduras de reentrantes): Permita que el mismo hilo adquiera el bloqueo varias veces sin bloquear. Útil en situaciones en las que una función se llama a sí misma recursivamente y necesita acceder a un recurso compartido.
* Lectura de lectura-escritura: Permita que varios hilos lean el recurso compartido simultáneamente, pero solo un hilo puede escribir a la vez. Esto mejora la concurrencia en comparación con un bloqueo mutex simple.
* Variables de condición: Se utiliza junto con las cerraduras para permitir que los hilos esperen que las condiciones específicas se hagan realidad antes de acceder a un recurso compartido. Proporcionan una sincronización más sofisticada que las cerraduras simples.
* semáforos: Generalizar cerraduras; Permiten que un número específico de subprocesos acceda a un recurso compartido simultáneamente. Un semáforo con un recuento de 1 es esencialmente un bloqueo mutex.
Consideraciones importantes:
* Granularidad de bloqueo: Elija el nivel apropiado de granularidad para sus cerraduras. El bloqueo de grano demasiado fino puede conducir a una sobrecarga excesiva, mientras que el bloqueo de grano demasiado grueso puede limitar la concurrencia.
* Prevención de punto muerto: Siempre adquiera cerraduras en el mismo orden para evitar los puntos de bloqueo. Use técnicas como la detección y evitación de punto muerto para mitigar el riesgo.
* hambre: Asegúrese de que no se bloquee ningún hilo para adquirir un bloqueo. Los mecanismos de equidad pueden ayudar a prevenir el hambre.
* Rendimiento: Las cerraduras introducen por encima. Considere mecanismos de sincronización alternativos como operaciones atómicas o estructuras de datos sin bloqueo cuando sea apropiado.
La implementación específica de bloqueos varía en entre los lenguajes de programación. Los ejemplos y conceptos proporcionados aquí son generales y se aplican en términos generales, pero la sintaxis exacta y los tipos de bloqueos disponibles diferirán en idiomas como Java, C ++, C#, GO, etc. Consulte la documentación de su idioma para obtener los detalles.