Monitor

Los monitor son una herramienta valiosa en programación concurrente y han sido ampliamente adoptados en diversos contextos para gestionar la concurrencia de manera segura y eficiente.
Suponga que se quiere implementar un contador que puede ser incrementado y decrementado por varios hilos simultáneamente, pero se debe asegurar de que estas operaciones sean atómicas y que siempre se respete la exclusión mutua.
Codificación
import threading
class MonitorContador:
def __init__(self):
self.valor = 0
self.mutex = threading.Lock()
def incrementar(self):
with self.mutex:
self.valor += 1
def decrementar(self):
with self.mutex:
self.valor -= 1
def obtener_valor(self):
with self.mutex:
return self.valor
# Crear una instancia del monitor
contador_monitor = MonitorContador()
# Definir una función que incrementa el contador
def aumentar_contador():
for _ in range(1000000):
contador_monitor.incrementar()
# Definir una función que decrementa el contador
def disminuir_contador():
for _ in range(1000000):
contador_monitor.decrementar()
# Crear hilos para incrementar y decrementar el contador
hilo_aumentar = threading.Thread(target=aumentar_contador)
hilo_disminuir = threading.Thread(target=disminuir_contador)
# Iniciar los hilos
hilo_aumentar.start()
hilo_disminuir.start()
# Esperar a que ambos hilos terminen
hilo_aumentar.join()
hilo_disminuir.join()
# Obtener el valor final del contador desde el monitor
valor_final = contador_monitor.obtener_valor()
print("Valor final del contador:", valor_final)
Explicación
En este ejemplo, la clase MonitorContador encapsula el contador y los métodos (incrementar, decrementar, obtener_valor) que operan sobre él. Se utiliza un cerrojo (mutex) para garantizar la exclusión mutua alrededor de las operaciones críticas. Los dos hilos (hilo_aumentar y hilo_disminuir) realizan incrementos y decrementos en paralelo, pero gracias al monitor, estas operaciones son seguras y el valor final del contador reflejará la suma y resta correctamente.