The Arc<T> documentation says:
impl<T> Sync for Arc<T> where T: Send + Sync + ?Sized
impl<T> Send for Arc<T> where T: Send + Sync + ?Sized
An Arc allows multiple threads to concurrently access the underlying T via an immutable reference &T. This is safe as long as T can't be modified in an unsynchronized manner via &T. This is true for all types with 'inherited mutability' (nearly all types) and false for the ones with unsynchronized 'interior mutability' (e.g. RefCell, ...).
As far as I understand it, the Send bound is not required here. For example, I think sharing my artificial type which implements Sync but not Send in an Arc is safe.
Lastly, &T itself also doesn't have this bound! In the documentation for Send and Sync we find:
impl<'a, T> Send for &'a T where T: Sync + ?Sized
impl<'a, T> Sync for &'a T where T: Sync + ?Sized
And as Arc<T> allows the same access to T as &T does, I don't understand why Arc<T> has the additional Send bound. Why is that?
'Arc' stands for 'Atomically Reference Counted'. The type Arc<T> provides shared ownership of a value of type T , allocated in the heap. Invoking clone on Arc produces a new Arc instance, which points to the same allocation on the heap as the source Arc , while increasing a reference count.
An integer the size of which is arch will be 32 bits on an x86 machine and 64 bits on an x64 machine.
I believe this is because an Arc owns the value it contains, and is thus responsible for dropping it.
Consider the following sequence:
T is created in thread 1. It is not Send, which means it is not safe to move this value to another thread.Arc handle.And just like that, we've moved a value of type T from one thread to another, violating memory safety.
&T doesn't require Send because dropping a &T never allows you to drop the underlying value.
Addendum: As an example of a type where this would be a problem, consider a type like struct Handle(usize); which is backed by a thread-local array of resources. If the Drop implementation for such a type is run on the wrong thread, this will lead to it either doing an out-of-bounds access (where it tries to destroy a resource that doesn't exist on this thread), or destroys a resource that's still in use.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With