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