Why T: Sync does not means Arc<T>: Sync

the defination is

impl Sync for Arc<T> where T: Sync + Send; e.g, T: Sync is not enough.
Any example to show a T: Sync, and Arc<T>: !Sync?

You can get back the ownership from a unique Arc using try_unwrap(). But the current unique owner might not have been created on the same thread where the original value lived, if the Arc was cloned and the original one was dropped in the meantime.

Since sending a reference-to-Arc to another thread allows you to clone() it inside that thread, &Arc<T>: Send and thus Arc<T>: Sync must be tied to T: Send.

2 Likes

std::sync::MutexGuard<'_, i32> is Sync but not Send, so Arc<MutexGuard<'_, i32>> is not Sync. If it were Sync, you could lock a Mutex<i32> on thread A, put the MutexGuard into an Arc, and send a reference to that Arc to thread B. After that, you could clone the Arc from thread B and drop the original Arc on thread A. At that point, thread B could take ownership of the MutexGuard using try_unwrap as @H2CO3 described, and then the guard would be dropped on a different thread from where it was created—which is unsound.

Actually, I don't think try_unwrap is even necessary: as long as thread B gets a unique Arc and no further cloning occurs, the contained value will be dropped on B when the Arc is dropped, right?

1 Like

Yep, the very Drop impl which may drop the T on another thread if the last Arc owner ends up here already causes the T : Send requirement. More generally, for any wrapper featuring shared ownership, the Send and Sync notions become entangled.

1 Like

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.