Skip to content
All writing Part 03 of 04 · [object Object]
Engineering · 1 min read

Python's `with lock:` Guarantees Release on Exception

Python's `with lock:` is sugar for acquire plus try/finally release, guaranteeing the lock frees itself even when the critical section throws an exception.

Python Under Multithreading

with lock: Guarantees Release Even on Exception

Manual acquire()/release() without try/finally means: if the body throws, the lock never releases — every subsequent caller trying to acquire it gets stuck, turning into a permanent deadlock.

with lock: is really syntactic sugar for acquire + try/finally release:

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

release() is guaranteed to run when the block ends — even if the body throws an exception.

Real-world case: the critical section of login() calls session.post() and raise_for_status(), both of which can throw. Using with self._login_lock: ensures the lock releases on a network error, preventing one failed login from blocking every subsequent login on that worker.

Every synchronization primitive in Python’s threading library supports with: Lock, RLock, Condition, Semaphore, BoundedSemaphore. Use with whenever possible.

Releasing a lock shouldn’t depend on the happy path. Use with, and hand it off to finally.


References:

Related: see the double-checked locking breakdown of two checks, two jobs, the finish-first, then-publish safe publication pattern, or go back to the four-lesson overview on making login thread-safe.

Tags #concurrency #python
// connect

Be brave | Be wise | Be grateful

21 BreakinCode

// elsewhere
LinkedInMedium (lang: en)Life RecordYoutube
wh:~$William Hung· © 2026 Taipei · GMT+8 · Available for collaboration