Ještě jednou a lépe: práce se zámky v Pythonu

Od Petr Zemek, 2013-12-15

Minule jsme si ukázali využití příkazu with při práci se soubory. Dneska se podíváme na to, jak jej využít při práci se zámky.

Původní kód

Vezměme si následující kód, který využívá zámky pro vzájemné vyloučení:

from threading import Lock
 
lock = Lock()
# ...
lock.acquire()
# Kritická sekce
lock.release()

Nejdříve se provede zavolání lock.acquire(), které zjistí, zda byl zámek již zamknut. Pokud ano, počká na jeho odemčení. Pokud ne, tak jej zamkne a vstoupí do kritické sekce, kde můžeme pracovat např. se sdílenými zdroji. Poté dojde k opuštění kritické sekce a odemčení zámku.

Proč takto raději ne?

Stejně jako minule, i zde nastane problém v případě, kdy během kritické sekce dojde k vyhození výjimky. V takovém případě se nezavolá lock.release() a může dojít k zablokování. Řešení je nasnadě:

lock.acquire()
try:
    # Kritická sekce
finally:
    lock.release()

To je ale značně zdlouhavé. Navíc to neřeší to, že se nesmí zapomenout na zavolání lock.release().

Jak to udělat lépe?

Jak již bylo řečeno v úvodu, tak opět využijeme příkaz with:

with lock:
    # Kritická sekce

Tento příkaz za nás automaticky zavolá lock.acquire(), provede kód v kritické sekci, a poté zavolá lock.release(), ať už došlo k vyhození výjimky či nikoliv. Nemusíme si tedy dělat starosti s odemčením zámku. Skvělé, že?

Obsah tohoto pole je soukromý a nebude veřejně zobrazen.

Filtrované HTML (využíváno)

  • Povolené HTML značky: <a href hreflang> <em> <strong> <cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <table>
  • Zvýraznění syntaxe kódu lze povolit přes následující značky: <code>, <blockcode>, <bash>, <c>, <cpp>, <haskell>, <html>, <java>, <javascript>, <latex>, <perl>, <php>, <python>, <ruby>, <rust>, <sql>, <text>, <vim>, <xml>, <yaml>.
  • Řádky a odstavce se zalomí automaticky.
  • Webové a e-mailové adresy jsou automaticky převedeny na odkazy.
CAPTCHA
12 + 3 =
Vyřešte tento jednoduchý matematický příklad a vložte výsledek. Např. pro 1+3 vložte 4.
Nějak se mi tady rozmohl spam, takže poprosím o ověření.