web-dev-qa-db-fra.com

Sémaphores sur Python

J'ai commencé à programmer en Python il y a quelques semaines et j'essayais d'utiliser Semaphores pour synchroniser deux threads simples, à des fins d'apprentissage. Voici ce que j'ai

import threading
sem = threading.Semaphore()

def fun1():
    while True:
        sem.acquire()
        print(1)
        sem.release()

def fun2():
    while True:
        sem.acquire()
        print(2)
        sem.release()

t = threading.Thread(target = fun1)
t.start()
t2 = threading.Thread(target = fun2)
t2.start()

Mais il continue à imprimer juste 1. Comment puis-je intercaler les impressions?

8
Victor Turrisi

Cela fonctionne bien, c’est juste que son impression est trop rapide pour que vous puissiez la voir. Essayez de mettre une time.sleep() dans les deux fonctions (une petite quantité) pour mettre le thread en veille pendant autant de temps, afin de pouvoir voir à la fois 1 et 2.

Exemple -

import threading
import time
sem = threading.Semaphore()

def fun1():
    while True:
        sem.acquire()
        print(1)
        sem.release()
        time.sleep(0.25)

def fun2():
    while True:
        sem.acquire()
        print(2)
        sem.release()
        time.sleep(0.25)

t = threading.Thread(target = fun1)
t.start()
t2 = threading.Thread(target = fun2)
t2.start()
7
Anand S Kumar

Vous pouvez également utiliser Lock/mutex comme suit:

import threading
import time

mutex = threading.Lock()  # equal to threading.Semaphore(1)


def fun1():
    while True:
        mutex.acquire()
        print(1)
        mutex.release()
        time.sleep(0.5)


def fun2():
    while True:
        mutex.acquire()
        print(2)
        mutex.release()
        time.sleep(0.5)

t1 = threading.Thread(target=fun1).start()
t2 = threading.Thread(target=fun2).start()

Autre type d'utilisation/plus simple:

import threading
import time

mutex = threading.Lock()  # equal to threading.Semaphore(1)


def fun1():
    while True:
        with mutex:
            print(1)
        time.sleep(0.5)


def fun2():
    while True:
        with mutex:
            print(2)
        time.sleep(0.5)

t1 = threading.Thread(target=fun1).start()
t2 = threading.Thread(target=fun2).start()

Remarque: en plus différence entre mutex et sémaphore , mutex VS sémaphore

1
Benyamin Jafari

J'ai utilisé ce code pour montrer comment un thread peut utiliser un sémaphore et l'autre thread attendra (non bloquant) jusqu'à ce que Sempahore soit disponible.

Cela a été écrit en utilisant Python3.6; Non testé sur aucune autre version.

Cela fonctionnera uniquement si la synchronisation est effectuée à partir du même thread. IPC de processus distincts échouera à l'aide de ce mécanisme.

import threading
from  time import sleep
sem = threading.Semaphore()

def fun1():
    print("fun1 starting")
    sem.acquire()
    for loop in range(1,5):
        print("Fun1 Working {}".format(loop))
        sleep(1)
    sem.release()
    print("fun1 finished")



def fun2():
    print("fun2 starting")
    while not sem.acquire(blocking=False):
        print("Fun2 No Semaphore available")
        sleep(1)
    else:
        print("Got Semphore")
        for loop in range(1, 5):
            print("Fun2 Working {}".format(loop))
            sleep(1)
    sem.release()

t1 = threading.Thread(target = fun1)
t2 = threading.Thread(target = fun2)
t1.start()
t2.start()
t1.join()
t2.join()
print("All Threads done Exiting")

Quand je lance ceci - je reçois la sortie suivante.

fun1 starting
Fun1 Working 1
fun2 starting
Fun2 No Semaphore available
Fun1 Working 2
Fun2 No Semaphore available
Fun1 Working 3
Fun2 No Semaphore available
Fun1 Working 4
Fun2 No Semaphore available
fun1 finished
Got Semphore
Fun2 Working 1
Fun2 Working 2
Fun2 Working 3
Fun2 Working 4
All Threads done Exiting
0
Tim Seed