Suppose one thread changes a game board while another uses it. The board is an array, so it cannot simply be declared _Atomic. Instead, place operations on the shared board inside a critical section protected by a mtx_t mutex. Smaller shared values that are _Atomic can be accessed without that mutex. section 20.4
Protecting a board update
The input thread acquires L->mtx with mtx_lock before calling life_birth9(L), then releases it with mtx_unlock. mtx_lock blocks until no other thread is inside a critical section protected by that mutex. The protection therefore depends on threads using the same mutex for the shared data. section 20.4
Acquiring a mutex also provides a visibility guarantee: after acquiring it, a thread can rely on operations performed before another thread released that same mutex having taken effect. TAKEAWAY: protect code paths that operate on otherwise unprotected shared data; use _Atomic for suitable small shared data. section 20.4 section 20.8
Protection must not come at the cost of permanently stalled threads:
- If a critical section needs several mutexes, acquire them in the same order across threads. Opposite orders can leave each thread waiting for a mutex held by the other. section 20.7
- Condition-variable waits need separate liveness care. Prefer cnd_timedwait over cnd_wait to avoid an indefinite wait. section 20.7
// thread A // thread B mtx_lock(&M);..........................mtx_lock(&N); mtx_lock(&N); /*waiting for B */ mtx_lock(&M); /*waiting for A */
The two-thread listing shows why a consistent mutex acquisition order matters: each thread holds the lock the other is waiting to acquire. section 20.7








