A memory barrier guarantees that all visible effects of prior instructions become observable before those of any subsequent instructions. Things that might reorder the observed order of effects are:
- Compilers (by reordering instructions)
- Out of order pipelines
- Cache systems with relaxed memory consistency (practically all on modern systems)
A mutex guarantees that only one thread holds the mutex at a time.
There is a relationship between the two concepts: a mutex is practically useless without at least partial memory barriers. Consider this example:
mutex_lock(a);
x = x+1;
mutex_unlock(a);
The lock operation must have at least an "acquire" barrier that prevents the load of x from appearing to happen before the lock is acquired. Likewise, the "unlock" operation must have at least a "release" barrier that prevents the store of x from appearing to happen after the lock is released. That is the lock-unlock pair form a cage from which operations cannot escape. (Though sometimes programmers are surprised when reordering causes operations to crawl into the cage!)
So locking a mutex and immediately unlocking it acts as a memory barrier, albeit a horribly inefficient one since it forces serial execution.