Semáforos en Python

Haider Ali 21 junio 2023
Semáforos en Python

En esta guía, aprenderemos cómo manejar subprocesos múltiples en Python usando semáforos. ¿Cómo tener acceso sincronizado a los hilos y la cantidad restringida de recursos?

Semáforos

Un controlador de sincronización es un semáforo. Semaphore proporciona acceso sincronizado a un número limitado de recursos para subprocesos.

Un semáforo se puede ver como una variable que representa cuántos recursos están disponibles ahora.

Por ejemplo, un estacionamiento en un centro comercial que funciona como un semáforo tiene varios espacios disponibles en un nivel determinado.

El valor del semáforo debe ser mayor o menor que los recursos disponibles. Las operaciones de adquirir y liberar están conectadas con el semáforo.

El valor del semáforo se reduce cuando un subproceso “adquiere” uno de los recursos que se utilizan para la sincronización. El valor del semáforo aumenta cuando un subproceso “libera” uno de los recursos sincronizados.

Semáforos en Python

La implementación de Python del concepto de semáforo utiliza una clase del módulo threading. Semáforo es el nombre de esta clase.

Las funciones acquire() y release() están incluidas en la clase Semaphore, junto con un constructor de funciones.

Si el recuento de semáforos es mayor que cero, se utiliza la función adquirir() para reducir el recuento. De lo contrario, se bloqueará hasta que el recuento sea mayor que 0.

Uno de los subprocesos que se encuentran en el semáforo se activa mediante el uso de la función release(), que también aumenta la cuenta del semáforo. Ahora comprendamos la sintaxis del semáforo.

object_name = threading.Semaphore(count)

El objeto de la clase Semáforo se indica mediante el nombre_objeto en la sintaxis anterior.

El número de subprocesos a los que se permite acceder a la vez se especifica mediante el argumento recuento de la clase Semáforo. El valor predeterminado de este parámetro es 1.

El valor del parámetro contar se reduce en uno cada vez que un subproceso utiliza la función adquirir(). El valor del parámetro count se incrementa en uno cada vez que un hilo utiliza la función release().

De acuerdo con esta afirmación, cada vez que llamemos al método adquirir(), el valor del parámetro contar disminuirá; sin embargo, cuando llamamos a la función release(), el valor del parámetro count aumentará. Echa un vistazo al siguiente código.

# import threading module
import threading

# creating instance of semaphore
sema = threading.Semaphore(1)


def test():
    # appling semaphore
    print(f"Value Of Semaphore --> {sema._value}")
    sema.acquire()
    print(f"acquired lock --> {threading.current_thread().name}")
    print(f"Value Of Semaphore --> {sema._value}")
    print(f"release lock --> {threading.current_thread().name}")
    sema.release()
    print(f"Value Of Semaphore --> {sema._value}")


# initializing threads
t1 = threading.Thread(target=test)
t2 = threading.Thread(target=test)
t3 = threading.Thread(target=test)
# executing threads
t1.start()
t2.start()
t3.start()

Los subprocesos se sincronizarán si count se establece en 1, como en el código anterior. Si observamos la salida del código anterior, notaremos que será el primer y segundo subproceso, luego el tercer subproceso tendrá acceso al código entre “adquirir” y “liberar”.

Value Of Semaphore --> 1
Value Of Semaphore --> 1
acquired lock --> Thread-1 (test)
Value Of Semaphore --> 0
Value Of Semaphore --> 0
release lock --> Thread-1 (test)
Value Of Semaphore --> 1
acquired lock --> Thread-2 (test)
Value Of Semaphore --> 0
release lock --> Thread-2 (test)
Value Of Semaphore --> 1
acquired lock --> Thread-3 (test)
Value Of Semaphore --> 0
release lock --> Thread-3 (test)
Value Of Semaphore --> 1

Si tuviera que cambiar el valor del recuento de 1 a 2, permitiría dos subprocesos al código restringido a la vez. Entonces, la salida será diferente.

Value Of Semaphore --> 2
acquired lock --> Thread-1 (test)
Value Of Semaphore --> 1
Value Of Semaphore --> 1
release lock --> Thread-1 (test)
Value Of Semaphore --> 1
Value Of Semaphore --> 1
acquired lock --> Thread-3 (test)
acquired lock --> Thread-2 (test)
Value Of Semaphore --> 0
Value Of Semaphore --> 0
release lock --> Thread-2 (test)
release lock --> Thread-3 (test)
Value Of Semaphore --> 1
Value Of Semaphore --> 2

Tenga en cuenta que el tiempo que tarda el semáforo en liberar el hilo se basa en la velocidad de su dispositivo, y cada vez será diferente. Puede probar el código anterior cambiando el valor del recuento en la instancia del semáforo.

Autor: Haider Ali
Haider Ali avatar Haider Ali avatar

Haider specializes in technical writing. He has a solid background in computer science that allows him to create engaging, original, and compelling technical tutorials. In his free time, he enjoys adding new skills to his repertoire and watching Netflix.

LinkedIn