Why *const T, *mut T : !Send + !Sync by default

while &T, &mut T is not?
and why Mutex: Sync needs T: Send?

Why *const T, *mut T : !Send + !Sync by default

Raw pointers are usually used for interacting with FFI, unsafe code, and sometimes that even implies interior mutability. Therefore, you actively need to consider whether a type containing a raw pointer is actually thread-safe. So, as a cautionary measure, raw pointers aren't Send or Sync, because marking them as such would be a thread safety footgun. If you specifically write your FFI-facing code in such a way that it is impossible to cause a race condition with them, then you can go ahead and manually, and unsafely, implement Send and/or Sync for your own types containing raw pointers. However, doing that automatically would be a footgun.

Since Mutex::lock() provides a mutable reference but only takes Self as an immutable reference, it is possible to acquire ownership of the inner value given only an immutable reference to a Mutex. Example:

let mutex = Mutex::new(Some(String::from("lol")));
let mut guard = mutex.lock().unwrap();
let inner = guard.take().unwrap();

Now, if the guard does this by-value stealing on a different thread than the one the Mutex and its inner value was created on, then the inner value ends up being moved to a different thread. Thus, it is necessary that T: Send if you want to have even immutable references to the Mutex in many threads.


This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.