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).
This trait is automatically derived when the compiler determines it's appropriate.
Implementors
impl<T: Sync + ?Sized> Sync for Unique<T>impl<T: ?Sized> !Sync for Shared<T>impl<T: ?Sized> !Sync for *const Timpl<T: ?Sized> !Sync for *mut Timpl Sync for AtomicBoolimpl Sync for AtomicIsizeimpl Sync for AtomicUsizeimpl<T> Sync for AtomicPtr<T>impl<T> !Sync for Cell<T>impl<T: ?Sized> !Sync for RefCell<T>impl<T: ?Sized> !Sync for UnsafeCell<T>impl<'a, T: Sync> Sync for Iter<'a, T>impl<'a, T: Sync> Sync for IterMut<'a, T>