Presentando el objeto Lock
Cuando se trabaja con hilos (threads) en Python, es común encontrar situaciones en las que múltiples hilos (threads) necesitan acceder y modificar recursos compartidos, como variables, archivos o bases de datos. Esto puede dar lugar a condiciones de carrera (race conditions), en las que el resultado final depende del tiempo relativo de ejecución de los hilos (threads), lo que potencialmente puede provocar la corrupción de datos u otros resultados no deseados.
Para abordar este problema, el módulo threading de Python proporciona el objeto Lock, que te permite controlar y coordinar el acceso a los recursos compartidos.
Comprendiendo el objeto Lock
El objeto Lock actúa como un mecanismo de exclusión mutua, asegurando que solo un hilo (thread) pueda acceder a un recurso compartido a la vez. Cuando un hilo (thread) adquiere un bloqueo (lock), otros hilos (threads) que intenten adquirir el mismo bloqueo (lock) se bloquearán hasta que el bloqueo (lock) se libere.
A continuación, se muestra un ejemplo de cómo usar el objeto Lock:
import threading
## Create a lock object
lock = threading.Lock()
## Shared resource
shared_variable = 0
def increment_shared_variable():
global shared_variable
## Acquire the lock
with lock:
## Critical section
shared_variable += 1
## Create and start two threads
thread1 = threading.Thread(target=increment_shared_variable)
thread2 = threading.Thread(target=increment_shared_variable)
thread1.start()
thread2.start()
## Wait for the threads to finish
thread1.join()
thread2.join()
print(f"Final value of shared_variable: {shared_variable}")
En este ejemplo, creamos un objeto Lock y lo usamos para proteger el acceso a la variable shared_variable. La declaración with lock: adquiere el bloqueo (lock), permitiendo que solo un hilo (thread) ejecute la sección crítica (el código que modifica el recurso compartido) a la vez. Esto asegura que la operación de incremento se realice de forma atómica, evitando las condiciones de carrera (race conditions).
Interbloqueos (deadlocks) y inanición (starvation)
Si bien el objeto Lock es una herramienta poderosa para sincronizar el acceso a los recursos compartidos, es importante ser consciente de los posibles problemas que pueden surgir, como los interbloqueos (deadlocks) y la inanición (starvation).
Los interbloqueos (deadlocks) ocurren cuando dos o más hilos (threads) están esperando a que el otro libere los bloqueos (locks), lo que resulta en una situación en la que ninguno de los hilos (threads) puede continuar. La inanición (starvation), por otro lado, ocurre cuando un hilo (thread) se ve continuamente negado el acceso a un recurso compartido, impidiéndole avanzar.
Para mitigar estos problemas, se recomienda seguir las mejores prácticas al usar bloqueos (locks), como siempre adquirir los bloqueos (locks) en el mismo orden, evitar el bloqueo innecesario y considerar mecanismos de sincronización alternativos como los objetos Semaphore o Condition.