Skip to content
所有文章 ‹ Part 03 of 04 · login 執行緒安全的血淚史
工程 · 1 min read

Python with lock:就算拋例外,鎖也一定會放

手動 acquire 與 release 少了 try/finally,一次例外就會讓鎖永遠不放。Python 的 with lock 語法糖能保證例外時鎖依然釋放。

多執行緒下的 Python

with lock: 保證例外時也會釋放鎖

手動 acquire()/release() 少了 try/finally,body 一拋錯,鎖就永遠放不掉,之後每個來取鎖的都卡住,變成永久死鎖。

with lock: 其實是 acquire + try/finally release 的語法糖:

with self._login_lock:   # lock.acquire()
    ...                  # try: ...  finally: lock.release()

區塊一結束,release() 一定會執行,連 body 拋例外時也一樣。

拿真實情境來說:login() 的臨界區會呼叫 session.post() + raise_for_status(),兩者都可能拋錯。改用 with self._login_lock: 就能確保網路一出錯鎖也會釋放,不會讓一次失敗的登入卡死該 worker 之後所有登入。

Python threading library 的同步原語全都吃 with:Lock、RLock、Condition、Semaphore、BoundedSemaphore。能用 with 就用。

鎖的釋放不該依賴 happy path。用 with,把它交給 finally。


參考來源:

延伸閱讀: 參見雙重檢查鎖定的兩個檢查各司其職拆解、先做完再發佈的安全發佈模式,或回到讓 login 執行緒安全的四筆學費總覽。

↑↓ 移動 ↵ 開啟 esc 關閉