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
- Is built on: Mutex
- Helps prevent: Liveness failure
- See also: Lock poisoning
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¶
- In a sibling library: Rust: Forgotten unlock ↗
- In a sibling library: Go: A mutex guards a counter ↗
- In the books: Rust Atomics and Locks, Mara Bos — ch. 4, 'Building Our Own Spin Lock' → 'A Safe Interface Using a Lock Guard'
- Reference: Wikipedia: Resource acquisition is initialization ↗