Sync only type makes no sense without Send in rust: You need to move objects across thread boundaries to make it sharable. Is this correct?

  • std::marker::Sync : a type is safe to use in a shared ownership model across threads
  • std::marker::Send : a type is safe to cross thread boundaries

A Sync only type makes no sense. You have to first move the object across thread boundaries to make it usable in a "true" shared context. You cannot share plain old references &T/&mut T across thread boundaries because the lifetimes (other than 'static) come into play.

  • What use cases will get covered by having a Sync only type ?
  • Sync trait seems to be of no value without a Send . Send is what enables sharing so why was Sync trait created ?

Please correct my assumptions if they are wrong.

There are certain things you can access safely across thread boundaries but cannot send between threads.

One example is a struct that holds a reference to a thread local static variable. You can still access it with shared memory, but you can't send it.

1 Like

You can move non-static references into scoped threads (std::thread::scope, rayon).


I understand the argument the Sync is of limited value without Send. E. g. using Arc will require a Send + Sync bound.

As @kpreid pointed out, with scoped threads (or similar API, such as rayon's join function), you can actually send non-static things between threads, so non-static references to Sync-only types can be used there.

However even if that wasn't the case, I cannot follow your argument why Sync should be useless. Even if Sync without Send wouldn't be useful, you'd still be distinguishing Send types (i. e. Send + !Sync ones) from Send + Sync types!!!

Like.. it's quite simple: if you share something, e. g. via Arc, you often need Send + Sync (though as mentioned above sometimes only Sync can be sufficient, too) and if you only need to send something, e. g. through a channel, then you only need Send. (Or if you share some data contained in a Mutex, then Send alone is sufficient, too.) Sync + Send clearly enables more things than just Send, and also it's implemented by fewer types. (E. g. a RefCell<T> or Cell<T> is not threadsafe when shared, but it's still Send [whenever T is Send].)


"thread local static" : example code snippet: scope in std::thread - Rust

@steffahn The rust doc on the marker module should really contain a section talking about the 3 cases:

  • Send + !Sync
  • Sync + !Send
  • Send + Sync

and provide guidance for users creating new types on how thread safety should be modeled for the new type. Even if not in the std crate doc at-least a section in the book/rustonomicon about this.

@steffahn The reply is really good. Thank you. This interpretation is really useful. Am new to rust so :slight_smile:


I have just fished the original version of this question as it had been posted to URLO out of our spam filter that had unfortunately caught it. It is getting engagement in both places now, so in case anyone wants to read all the existing answers or write new answers (especially longer answers with more effort spent) it may be valuable to take a look into the other thread as well to be aware of what was already said

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.