Module std::sync::atomic

1.0.0 · source ·
Expand description

原子类型

原子类型提供线程之间的原始共享内存通信,并且是其他并发类型的构建块。

Rust atomics 目前遵循与 C++20 atomics 相同的规则,特别是 atomic_ref。 基本上,为 Rust 原子类型之一创建一个共享引用对应于在 C++ 中创建一个 atomic_ref; atomic_ref 是在视频生命周期结束时共享的。 (一个 Rust 原子类型,它是独占的或在一个惰性引用之后对应于 C++ 中的 “atomic object”,因为它可以通过非原子操作访问。)

该模块定义了一些原始类型的原子版本,包括 AtomicBoolAtomicIsizeAtomicUsizeAtomicI8AtomicU16 等。 原子类型表示可正确使用的操作,这些操作可在线程之间同步更新。

每种方法都使用一个 Ordering 来表示该操作的内存屏障的强度。这些顺序与 C++20 原子排序 相同。有关更多信息,请参见 nomicon

原子变量可以安全地在线程之间共享 (它们实现 Sync),但是它们本身并不提供共享机制并遵循 Rust 的 线程模型

共享原子变量的最常见方法是将其放入 Arc (原子引用计数的共享指针)。

原子类型可以存储在静态变量中,可以使用常量初始化程序 (如 AtomicBool::new) 进行初始化。原子静态常用于懒惰的初始化。

Portability

如果可用,则保证该模块中的所有原子类型均为 无锁。这意味着他们没有在内部获得一个整体互斥锁。不能保证原子类型和操作无需等待。 这意味着可以使用比较和交换循环来实现类似 fetch_or 的操作。

原子操作可以在指令层用更大的原子来实现。例如,某些平台使用 4 字节原子指令来实现 AtomicI8。 请注意,此仿真不应影响代码的正确性,这只是需要注意的事情。

此模块中的原子类型可能并非在所有平台上都可用。但是,这里的原子类型都是广泛可用的,并且通常可以依赖现有原子类型。一些值得注意的例外是:

  • 具有 32 位指针的 PowerPC 和 MIPS 平台没有 AtomicU64AtomicI64 类型。
  • 不支持 Linux 的 armv5te 等 ARM 平台只提供 loadstore 操作,不支持 Compare 和 Swap (CAS) 操作,如 swapfetch_add 等。 此外,在 Linux 上,这些 CAS 操作是通过 操作系统支持 实现的,这可能会降低性能。
  • 带有 thumbv6m 的 ARM 目标仅提供 loadstore 操作,不支持 (CAS) 比较和交换操作,如 swapfetch_add 等。

请注意,可能会添加 future 平台,这些平台也不支持某些原子操作。最大程度地讲,可移植代码将要注意所使用的原子类型。 AtomicUsizeAtomicIsize 通常是最便携的,但即便如此,它们也并非随处可用。 作为参考,std 库需要 AtomicBools 和 pointer-sized atomics,尽管 core 不需要。

#[cfg(target_has_atomic)] 属性可用于根据目标支持的位宽进行有条件的编译。 它是为每个支持的大小设置的键值选项,其值 “8”、“16”、“32”、“64”、“128” 和 “ptr” 用于指针大小的原子。

Examples

一个简单的自旋锁:

use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::{hint, thread};

fn main() {
    let spinlock = Arc::new(AtomicUsize::new(1));

    let spinlock_clone = Arc::clone(&spinlock);
    let thread = thread::spawn(move|| {
        spinlock_clone.store(0, Ordering::SeqCst);
    });

    // 等待另一个线程释放锁
    while spinlock.load(Ordering::SeqCst) != 0 {
        hint::spin_loop();
    }

    if let Err(panic) = thread.join() {
        println!("Thread had an error: {panic:?}");
    }
}
Run

保持活动线程的数量:

use std::sync::atomic::{AtomicUsize, Ordering};

static GLOBAL_THREAD_COUNT: AtomicUsize = AtomicUsize::new(0);

let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::SeqCst);
println!("live threads: {}", old_thread_count + 1);
Run

Structs

  • 可以在线程之间安全共享的布尔类型。
  • 可以在线程之间安全共享的整数类型。
  • 可以在线程之间安全共享的整数类型。
  • 可以在线程之间安全共享的整数类型。
  • 可以在线程之间安全共享的整数类型。
  • 可以在线程之间安全共享的整数类型。
  • 可以在线程之间安全共享的裸指针类型。
  • 可以在线程之间安全共享的整数类型。
  • 可以在线程之间安全共享的整数类型。
  • 可以在线程之间安全共享的整数类型。
  • 可以在线程之间安全共享的整数类型。
  • 可以在线程之间安全共享的整数类型。

Enums

Constants

Functions

  • 编译器内存栅栏。
  • 原子栅栏。
  • spin_loop_hintDeprecated
    向处理器发出信号,通知它处于忙于等待的自旋循环 (自旋锁) 中。