Now that we have a good grounding on the atomic primitives available to us in the Rust standard library, and have, moreover, a solid theoretical background, it's time for us to build on these foundations. In the past few chapters, we've been teasing our intention to build up mutexes and semaphores from primitives and, well, now the time has come.
Now that we understand linearizability and memory orderings, let's ask ourselves a question. What exactly is a mutex? We know its properties as an atomic object:
- Mutex supports two operations, lock and unlock.
- A mutex is either locked or unlocked.
- The operation lock will move a mutex into a locked state if and only if the mutex is unlocked. The thread that completes lock is said to hold the lock.
- The operation unlock will move a mutex into unlocked state if an only if the mutex is previously locked and the caller of unlock is the holder of the lock.
- All loads and stores which occur after and before a lock in program order...