Semaphore

Loenduriga (threading.Semaphore(value=1)) saab määrata piirarvu, mitu lõime tohib samaaegselt ressurssi kasutada. Lõime acquire() kutsel lahutatakse 1 ja release() kutsel liidetakse 1 loendurile. Jõudes nulli blokeeritakse uued acquire() kutse teinud lõimed kuni ressurssi kasutavate lõimede arv väheneb.

../_images/semaphore.png

Ressursil nagu printer on printimise piirarvuks 1, mitu lõime ei saa samalaegselt dokumenti printida.

threading.BoundedSemaphore(value=1) on ka piiratud ressursihalduseks mõeldud. Tema eeliseks Semaphore-ist ees on kontroll, et ressursi ei vabastaks rohkem lõimi kui ressursi kasutus (rohkem release() kutseid kui acquire()). Viimast võib juhtuda näiteks koodi struktuuri vea tõttu.

Meetodid

  • acquire(blocking=True, timeout=None)
    1. blocking=True - lõim ootab kuni ressurss vabaneb ehk loendur > 0. blocking=False korral lõim jätkab tööd ressursita.

    2. timeout - lõim ootab kuni määratud aja.

  • release(n=1)
    1. Loendurit suurendatakse n võrra. Ehk lõim/lõimed ei vaja enam ressurssi. Kui loendur oli 0 äratatakse kuni n ootel lõime.

Rohkem lõimi kui loendur korraga lubab:

sem = threading.Semaphore(2)

def access_resource(name):
    with sem:  # context manager, automatic acquire/release
        print(f"{name} Got resource")
        time.sleep(1)
        print(f"{name} Don't need it anymore")

threads = [threading.Thread(target=access_resource, args=(f"T{i}",)) for i in range(5)]
[t.start() for t in threads]
[t.join() for t in threads]