Skip to content

Mutex

Category: Synchronization · Status: stub · Lessons: chapter 02, Shared state

One line: A lock that one task holds at a time; any other task that tries to take it waits until it is released.

Also called: lock, mutual exclusion lock.

How it connects

flowchart LR
  n_atomic_variable["Atomic variable"]
  n_channel["Channel"]
  n_condition_variable["Condition variable"]
  n_contention["Contention"]
  n_deadlock["Deadlock"]
  n_futex["Futex"]
  n_gil["Global interpreter lock"]
  n_interior_mutability["Interior mutability"]
  n_monitor["Monitor"]
  n_mutex["Mutex"]
  n_mutual_exclusion["Mutual exclusion"]
  n_priority_inversion["Priority inversion"]
  n_read_write_lock["Read-write lock"]
  n_reentrant_lock["Reentrant lock"]
  n_scoped_lock["Scoped locking"]
  n_spinlock["Spinlock"]
  n_transactional_memory["Transactional memory"]
  n_atomic_variable ---|or| n_mutex
  n_channel ---|or| n_mutex
  n_condition_variable -->|uses| n_mutex
  n_gil -->|uses| n_mutex
  n_interior_mutability -->|uses| n_mutex
  n_monitor -->|uses| n_mutex
  n_mutex ---|or| n_transactional_memory
  n_mutex -->|can cause| n_contention
  n_mutex -->|can cause| n_deadlock
  n_mutex -->|can cause| n_priority_inversion
  n_mutex -->|is a| n_mutual_exclusion
  n_mutex -->|uses| n_futex
  n_read_write_lock -->|is a| n_mutex
  n_reentrant_lock -->|is a| n_mutex
  n_scoped_lock -->|uses| n_mutex
  n_spinlock -->|is a| n_mutex
  classDef center stroke-width:3px
  class n_mutex center
  classDef outside stroke-dasharray: 4 3
  class n_atomic_variable,n_channel,n_condition_variable,n_contention,n_deadlock,n_futex,n_gil,n_interior_mutability,n_monitor,n_mutual_exclusion,n_priority_inversion,n_read_write_lock,n_reentrant_lock,n_scoped_lock,n_spinlock,n_transactional_memory outside

In each language

Rust std::sync::Mutex contains the data it guards; the guard unlocks when dropped, and a panic while holding it poisons the lock
Go sync.Mutex: the zero value is unlocked, it must not be copied after first use, and it is not tied to the goroutine that locked it; Lock returns nothing, so there is no poisoning
C mtx_t from C11 <threads.h>: mtx_plain or mtx_timed, optionally combined with mtx_recursive
C++ std::mutex: locking it again ↗ from the owning thread is undefined behaviour
Java The monitor behind synchronized, or ReentrantLock, which behaves like it and adds tryLock, timed waits and a fairness option; both are reentrant
Python threading.Lock is not owned by the thread that locked it; RLock is the reentrant one
C# The lock statement ↗ on a System.Threading.Lock, or on any reference object through Monitor
Kotlin Mutex in kotlinx.coroutines suspends the coroutine instead of blocking a thread, and is non-reentrant
Swift Mutex in the Synchronization module protects shared mutable state via mutual exclusion
Haskell An MVar holding (): takeMVar to lock, putMVar to unlock, with FIFO wake-ups
The operating system POSIX pthread_mutex_lock with normal, error-checking, recursive and robust mutexes; on Linux they are built on futexes ↗

Where to read more