Trait std::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 for Unique<T> where T: Sync + ?Sized
impl<T> !Sync for Shared<T> where T: ?Sized
impl<T> !Sync for *const T where T: ?Sized
impl<T> !Sync for *mut T where T: ?Sized
impl Sync for AtomicBool
impl Sync for AtomicIsize
impl Sync for AtomicUsize
impl<T> Sync for AtomicPtr<T>
impl<T> !Sync for UnsafeCell<T> where T: ?Sized
impl<'a, T> Sync for Iter<'a, T> where T: Sync
impl<'a, T> Sync for IterMut<'a, T> where T: Sync
impl<T> Sync for Arc<T> where T: Send + Sync + ?Sized
impl<T> Sync for Weak<T> where T: Send + Sync + ?Sized
impl<T> Sync for ArcInner<T> where T: Send + Sync + ?Sized
impl<T> !Sync for Rc<T> where T: ?Sized
impl<T> !Sync for Weak<T> where T: ?Sized
impl<K, V> Sync for Root<K, V> where V: Sync, K: Sync
impl<BorrowType, K, V, Type> Sync for NodeRef<BorrowType, K, V, Type> where K: Sync, V: Sync
impl<T> Sync for Rawlink<T> where T: Sync
impl<'a> Sync for Drain<'a>
impl<T> Sync for IntoIter<T> where T: Sync
impl<'a, T> Sync for Drain<'a, T> where T: Sync
impl<'a, T> Sync for Drain<'a, T> where T: Sync
impl<K: Sync, V: Sync> Sync for RawTable<K, V>
impl<'a, K: Sync, V: Sync> Sync for Iter<'a, K, V>
impl<'a, K: Sync, V: Sync> Sync for IterMut<'a, K, V>
impl<K: Sync, V: Sync> Sync for IntoIter<K, V>
impl<'a, K: Sync, V: Sync> Sync for Drain<'a, K, V>
impl<T: Send> Sync for Queue<T>
impl Sync for Dummy
impl<T: ?Sized + Send> Sync for Mutex<T>
impl<T: ?Sized + Send> Sync for RwLock<T>