Trait core::marker::Sync [] [src]

pub unsafe trait Sync { }

Types that can be safely shared between threads when aliased.

The precise definition is: a type T is Sync if &T is thread-safe. In other words, there is no possibility of data races when passing &T references between threads.

As one would expect, primitive types like u8 and f64 are all Sync, and so are simple aggregate types containing them (like tuples, structs and enums). More instances of basic Sync types include "immutable" types like &T and those with simple inherited mutability, such as Box<T>, Vec<T> and most other collection types. (Generic parameters need to be Sync for their container to be Sync.)

A somewhat surprising consequence of the definition is &mut T is Sync (if T is Sync) even though it seems that it might provide unsynchronized mutation. The trick is a mutable reference stored in an aliasable reference (that is, & &mut T) becomes read-only, as if it were a & &T, hence there is no risk of a data race.

Types that are not Sync are those that have "interior mutability" in a non-thread-safe way, such as Cell and RefCell in std::cell. These types allow for mutation of their contents even when in an immutable, aliasable slot, e.g. the contents of &Cell<T> can be .set, and do not ensure data races are impossible, hence they cannot be Sync. A higher level example of a non-Sync type is the reference counted pointer std::rc::Rc, because any reference &Rc<T> can clone a new reference, which modifies the reference counts in a non-atomic way.

For cases when one does need thread-safe interior mutability, types like the atomics in std::sync and Mutex & RWLock in the sync crate do ensure that any mutation cannot cause data races. Hence these types are Sync.

Any types with interior mutability must also use the std::cell::UnsafeCell wrapper around the value(s) which can be mutated when behind a & reference; not doing this is undefined behavior (for example, transmute-ing from &T to &mut T is invalid).