Why Arc<Mutex<SomeType>> still implies SomeType must be Sync + Send?

In Rust, if I have a type that is not safe to send between threads, I wrap it with Arc<Mutex<T>>. This way I'm guaranteed that when I access it, I need to unlock it first. However, Rust still complains when SomeType does not implement Send + Sync.

Shoudln't it work for any type? In my case, SomeType is a struct that accesses a C object through FFI, so I cannot mark it as Sync + Send.

What can I do in this case and why Rust wont accept Arc<Mutex<SomeType>> as safe to share between threads?

Isn't it requires just Send? The Mutex<T> is to share T: !Sync types between threads, but Send is still needed since you can use mutex as a channel to transfer values between threads. std::mem::swap() to put a value in a thread, and swap it out in another thread, and it's moved.

4 Likes

Here is what the std docs say

Arc<T> will implement Send and Sync as long as the T implements Send and Sync . Why can't you put a non-thread-safe type T in an Arc<T> to make it thread-safe? This may be a bit counter-intuitive at first: after all, isn't the point of Arc<T> thread safety? The key is this: Arc<T> makes it thread safe to have multiple ownership of the same data, but it doesn't add thread safety to its data. Consider Arc< RefCell<T> > . RefCell<T> isn't Sync , and if Arc<T> was always Send , Arc< RefCell<T> > would be as well. But then we'd have a problem: RefCell<T> is not thread safe; it keeps track of the borrowing count using non-atomic operations.

1 Like

Generally if a type may not be sent across threads at all, then it doesn't matter if you put it behind a mutex. You still may not move it across threads.

A mutex lets you guarantee that no two threads access it at the same time, which means you don't need Sync. But you must still have Send on the inner type.

2 Likes