Movatterモバイル変換


[0]ホーム

URL:


Module sync

std

Modulesync 

1.0.0 ·Source
Expand description

Useful synchronization primitives.

§The need for synchronization

Conceptually, a Rust program is a series of operations which willbe executed on a computer. The timeline of events happening in theprogram is consistent with the order of the operations in the code.

Consider the following code, operating on some global static variables:

// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint#![allow(static_mut_refs)]staticmutA: u32 =0;staticmutB: u32 =0;staticmutC: u32 =0;fnmain() {unsafe{        A =3;        B =4;        A = A + B;        C = B;println!("{A} {B} {C}");        C = A;    }}

It appears as if some variables stored in memory are changed, an additionis performed, result is stored inA and the variableC ismodified twice.

When only a single thread is involved, the results are as expected:the line7 4 4 gets printed.

As for what happens behind the scenes, when optimizations are enabled thefinal generated machine code might look very different from the code:

  • The first store toC might be moved before the store toA orB,as if we had writtenC = 4; A = 3; B = 4.

  • Assignment ofA + B toA might be removed, since the sum can be storedin a temporary location until it gets printed, with the global variablenever getting updated.

  • The final result could be determined just by looking at the codeat compile time, soconstant folding might turn the wholeblock into a simpleprintln!("7 4 4").

The compiler is allowed to perform any combination of theseoptimizations, as long as the final optimized code, when executed,produces the same results as the one without optimizations.

Due to theconcurrency involved in modern computers, assumptionsabout the program’s execution order are often wrong. Access toglobal variables can lead to nondeterministic results,even ifcompiler optimizations are disabled, and it isstill possibleto introduce synchronization bugs.

Note that thanks to Rust’s safety guarantees, accessing global (static)variables requiresunsafe code, assuming we don’t use any of thesynchronization primitives in this module.

§Out-of-order execution

Instructions can execute in a different order from the one we define, due tovarious reasons:

  • Thecompiler reordering instructions: If the compiler can issue aninstruction at an earlier point, it will try to do so. For example, itmight hoist memory loads at the top of a code block, so that the CPU canstartprefetching the values from memory.

    In single-threaded scenarios, this can cause issues when writingsignal handlers or certain kinds of low-level code.Usecompiler fences to prevent this reordering.

  • Asingle processor executing instructionsout-of-order:Modern CPUs are capable ofsuperscalar execution,i.e., multiple instructions might be executing at the same time,even though the machine code describes a sequential process.

    This kind of reordering is handled transparently by the CPU.

  • Amultiprocessor system executing multiple hardware threadsat the same time: In multi-threaded scenarios, you can use twokinds of primitives to deal with synchronization:

    • memory fences to ensure memory accesses are made visible toother CPUs in the right order.
    • atomic operations to ensure simultaneous access to the samememory location doesn’t lead to undefined behavior.

§Higher-level synchronization objects

Most of the low-level synchronization primitives are quite error-prone andinconvenient to use, which is why the standard library also exposes somehigher-level synchronization objects.

These abstractions can be built out of lower-level primitives.For efficiency, the sync objects in the standard library are usuallyimplemented with help from the operating system’s kernel, which isable to reschedule the threads while they are blocked on acquiringa lock.

The following is an overview of the available synchronizationobjects:

  • Arc: Atomically Reference-Counted pointer, which can be usedin multithreaded environments to prolong the lifetime of somedata until all the threads have finished using it.

  • Barrier: Ensures multiple threads will wait for each otherto reach a point in the program, before continuing execution alltogether.

  • Condvar: Condition Variable, providing the ability to blocka thread while waiting for an event to occur.

  • mpsc: Multi-producer, single-consumer queues, used formessage-based communication. Can provide a lightweightinter-thread synchronisation mechanism, at the cost of someextra memory.

  • mpmc: Multi-producer, multi-consumer queues, used formessage-based communication. Can provide a lightweightinter-thread synchronisation mechanism, at the cost of someextra memory.

  • Mutex: Mutual Exclusion mechanism, which ensures that atmost one thread at a time is able to access some data.

  • Once: Used for a thread-safe, one-time global initialization routine.Mostly useful for implementing other types likeOnceLock.

  • OnceLock: Used for thread-safe, one-time initialization of avariable, with potentially different initializers based on the caller.

  • LazyLock: Used for thread-safe, one-time initialization of avariable, using one nullary initializer function provided at creation.

  • RwLock: Provides a mutual exclusion mechanism which allowsmultiple readers at the same time, while allowing only onewriter at a time. In some cases, this can be more efficient thana mutex.

Modules§

atomic
Atomic types
mpsc
Multi-producer, single-consumer FIFO queue communication primitives.
mpmcExperimental
Multi-producer, multi-consumer FIFO queue communication primitives.
nonpoisonExperimental
Non-poisoning synchronous locks.
poisonExperimental
Synchronization objects that employ poisoning.

Structs§

Arc
A thread-safe reference-counting pointer. ‘Arc’ stands for ‘AtomicallyReference Counted’.
Barrier
A barrier enables multiple threads to synchronize the beginningof some computation.
BarrierWaitResult
ABarrierWaitResult is returned byBarrier::wait() when all threadsin theBarrier have rendezvoused.
Condvar
A Condition Variable
LazyLock
A value which is initialized on the first access.
Mutex
A mutual exclusion primitive useful for protecting shared data
MutexGuard
An RAII implementation of a “scoped lock” of a mutex. When this structure isdropped (falls out of scope), the lock will be unlocked.
Once
A low-level synchronization primitive for one-time global execution.
OnceLock
A synchronization primitive which can nominally be written to only once.
OnceState
State yielded toOnce::call_once_force()’s closure parameter. The statecan be used to query the poison status of theOnce.
PoisonError
A type of error which can be returned whenever a lock is acquired.
RwLock
A reader-writer lock
RwLockReadGuard
RAII structure used to release the shared read access of a lock whendropped.
RwLockWriteGuard
RAII structure used to release the exclusive write access of a lock whendropped.
WaitTimeoutResult
A type indicating whether a timed wait on a condition variable returneddue to a time out or not.
Weak
Weak is a version ofArc that holds a non-owning reference to themanaged allocation.
ExclusiveExperimental
Exclusive providesmutable access, also referred to asexclusiveaccess to the underlying value. However, it only permitsimmutable, orsharedaccess to the underlying value when that value isSync.
MappedMutexGuardExperimental
An RAII mutex guard returned byMutexGuard::map, which can point to asubfield of the protected data. When this structure is dropped (falls outof scope), the lock will be unlocked.
MappedRwLockReadGuardExperimental
RAII structure used to release the shared read access of a lock whendropped, which can point to a subfield of the protected data.
MappedRwLockWriteGuardExperimental
RAII structure used to release the exclusive write access of a lock whendropped, which can point to a subfield of the protected data.
ReentrantLockExperimental
A re-entrant mutual exclusion lock
ReentrantLockGuardExperimental
An RAII implementation of a “scoped lock” of a re-entrant lock. When thisstructure is dropped (falls out of scope), the lock will be unlocked.
UniqueArcExperimental
A uniquely ownedArc.

Enums§

TryLockError
An enumeration of possible errors associated with aTryLockResult whichcan occur while trying to acquire a lock, from thetry_lock method on aMutex or thetry_read andtry_write methods on anRwLock.

Constants§

ONCE_INITDeprecated
Initialization value for staticOnce values.

Type Aliases§

LockResult
A type alias for the result of a lock method which can be poisoned.
TryLockResult
A type alias for the result of a nonblocking locking method.

[8]ページ先頭

©2009-2026 Movatter.jp