lunes, 12 de octubre de 2015

Maricela Ocaña Martínez
Programación Paralela y distribuida

Semáforos en Python.

A continuación se describirá brevemente que son los semáforos, así como también su funcionalidad y un pequeño ejemplo.

Semaphore
Uno de los mecanismos más antiguos de sincronización de hilos son los semáforos. Un semáforo permite acceder a un determinado recurso a un número máximo de hilos simultáneamente. Si hay más hilos que el máximo permitido, los pone en espera y los va dejando pasar según van terminando los que están activos. Un semáforo actúa como un contador con un valor inicial. Cada vez que un hilo llama a Semaphore.acquire(), el contador se decrementa en 1 y se deja pasar al hilo. En el momento que el contador se hace cero, NO se deja pasar al siguiente hilo que llame a acquire(), sino que lo deja bloqueado. Cada vez que se llama a Semaphore.release(), el contador se incrementa en 1. Si se hace igual a cero, libera al siguiente hilo en la cola de espera.
Los semáforos sirven para permitir el acceso a un recurso que admite un número máximo de hilos simultáneos. Por ejemplo, si cada hilo abre su conexión a base de datos y sólo queremos un máximo de cinco conexiones abiertas simultáneamente, un semáforo puede ser una opción.

En el código, se debe crear el semáforo indicando el valor inicial del contador (número máximo de hilos que pueden estar activos simultáneamente).

from threading import Semaphore
...
semaforo = Semaphore(5)
Y luego, cada hilo, hace lo siguiente.
semaforo.acquire()
# Aqui el hilo realiza su trabajo
semaforo.release()

Ejemplo de semáforos en Python. 

'''El main prepara un semaforo que
solo permite cinco hilos activos simultaneamente. El main arranca
10 hilos y les pasa el semaforo. Cada hilo espera el semaforo, un
tiempo aleatorio y termina.
En la salida del programa vemos que los cinco primeros hilos entran
inmediatamante y segun van terminando, va entrando el siguiente'''


from threading import Thread, Semaphore
import time, random

# Hilo a arrancar
class MiHilo(Thread):
    # Se le pasa un numero identificador del hilo y un semaforo
    def __init__(self, numero_hilo, semaforo):
        Thread.__init__(self)
        self.semaforo=semaforo
        self.numero_hilo = numero_hilo
        
    def run(self):
        # Espera al semaforo
        semaforo.acquire()
        print "Entra hilo "+str(self.numero_hilo)
        # Pierde un tiempo aleatorio
        time.sleep(random.randrange(1,10,1))
        print "Fin hilo " + str(self.numero_hilo)
        # Pone verde el semaforo para el siguiente y
        # termina
        semaforo.release()          
        
if __name__ == '__main__':
    random.seed()
    # Semaforo que permite pasar a cinco simultaneamente
    semaforo = Semaphore(5)
    # Se arrancan diez hilos
    for i in range(0,10):
       hilo=MiHilo(i,semaforo)
       hilo.start()
       print "Arrancado hilo "+str(i)

La información presentada anteriormente fue tomada de Chuwiki - Hilos con Python.