Skip to content

Scoped locking

Category: Synchronization · Status: stub · Lessons: chapter 03, When locks go wrong (planned)

One line: Tying a lock's release to leaving a scope — a guard object, defer, with, synchronized — so that no path out of the code can forget to unlock.

Also called: lock guard, RAII guard, lock_guard, defer unlock.

How it connects

flowchart LR
  n_liveness_failure["Liveness failure"]
  n_mutex["Mutex"]
  n_scoped_lock["Scoped locking"]
  n_scoped_lock -->|prevents| n_liveness_failure
  n_scoped_lock -->|uses| n_mutex
  classDef center stroke-width:3px
  class n_scoped_lock center
  classDef outside stroke-dasharray: 4 3
  class n_liveness_failure,n_mutex outside

In each language

Rust MutexGuard is an RAII scoped lock: the mutex unlocks when the guard is dropped
Go defer mu.Unlock() on the line after Lock: deferred calls ↗ run however the function returns, a panic included — but the defer is a line you must remember
C++ std::lock_guard for one mutex, std::scoped_lock (C++17) for several, with deadlock avoidance
Java synchronized blocks release on any exit; a Lock needs unlock() as the first statement of a finally block
Python with lock:threading primitives ↗ release when the block is exited
C# The lock statement ↗ expands to try/finally, or to using (x.EnterScope()) for a System.Threading.Lock
JavaScript navigator.locks.request releases the lock automatically when the callback returns or throws
Kotlin Mutex.withLock runs a block under the lock and releases it afterwards

Where to read more