Synchronization PrimitivesMutexes & LocksMedium⏱️ ~2 min

Common Mutex Patterns and Pitfalls

Key Insight
Always pair lock with unlock. Think of them like parentheses: every open must have a close.
Common Pitfalls
Forget Unlocklock()workreturn early// unlock never called!Double Locklock()call helper()helper also calls lock()// DEADLOCK!RAII Pattern{ Guard g(mutex); work();} // auto unlockException safe!

Pitfall 1: Forget To Unlock

If you return early or throw an exception without unlocking, the mutex stays locked forever. All other threads block indefinitely.

Pitfall 2: Double Lock (Self-Deadlock)

You hold a lock and call a function that also tries to lock the same mutex. Unless you have a recursive mutex, deadlock. The thread waits for itself.

Solution: RAII (Resource Acquisition Is Initialization)

Use lock guards that automatically unlock when they go out of scope. In C++: std::lock_guard. In Java: try-with-resources or synchronized. In Python: with lock:.

{
  std::lock_guard<std::mutex> g(m);
  // work here
} // unlock automatic
Rule: Never call lock() and unlock() manually. Use RAII wrappers. They guarantee cleanup even on exceptions.
💡 Key Takeaways
Always pair lock with unlock. Early returns and exceptions can leave locks held forever.
Never block on another semaphore while holding a mutex. This is a common deadlock source.
Use RAII or try/finally to guarantee unlock even when exceptions occur.
Keep critical sections short. The longer you hold a lock, the more you block other threads.
Blocking inside a critical section is especially dangerous: it prevents progress and risks deadlock.
📌 Examples
1Java try/finally: lock.lock(); try { work(); } finally { lock.unlock(); }
2C++ RAII: std::lock_guard<std::mutex> guard(mutex); // automatically unlocks when guard goes out of scope
← Back to Mutexes & Locks Overview