Search code examples
multithreadingrustthread-safetymutex

Why is it false that anything wrapped inside Mutex is thread safe?


It seems to me that if a data structure requires a lock for its contents to be accessed, then it doesn't matter what sort of data structure is inside. Even if the stuff on the inside is not thread safe (neither Send nor Sync), there will never be a situation where data races occur since only one thread will be allowed to work on it at a given time.

Yet, in Rust, Mutex is Send or Sync only if the interior is correspondingly Send or Sync.

Is there a case where we lose memory safety despite requiring a lock?


Solution

  • Consider the reason why a type may not be Send, and then consider if Mutex remedies that reason.

    The type Rc is !Send because it holds a shared resource that is not managed atomically. Thus it could cause a data race if two handles to the same resource were used on separate threads simultaneously. Even if one or both were wrapped in mutexes, that doesn't address the thread-safety of the type.

    Another case (though weird in this situation) is a MutexGuard itself is !Send because it relies on system facilities that requires the unlock to happen on the same thread as the lock was acquired (source). If a Mutex was Send regardless of its contents, then you could use it to smuggle the guard to another thread and violate those invariants (and cause UB as far as the source above reports).

    So a Mutex providing exclusivity does not automatically protect the type from other reasons why thread-locality is a concern.