鉴于 U32 已经实现了 Sync,为什么要在 Rust 中使用 AtomicU32?

Gyg*_*xis 3 multithreading types atomic thread-safety rust

std::sync::atomic模块包含许多基本类型的原子变体,其声明的目的是这些类型现在是线程安全的。然而,与原子类型相对应的所有基元都已经实现了SendSync,因此应该已经是线程安全的。这些类型背后的原因是什么Atomic

bk2*_*204 5

一般来说,非原子整数可以安全地跨线程共享,因为它们是不可变的。如果您尝试修改该值,则在大多数情况下会隐式创建一个新值,因为它们是Copy. 但是,跨线程共享对 a 的可变引用(或者对同一值同时具有可变和不可变引用)是不安全的u32,这实际上意味着您将无法修改该变量并让另一个线程看到该变量结果。原子类型有一些额外的行为使其安全。

在更一般的情况下,使用非原子操作并不能保证一个线程中所做的更改在另一个线程中可见。许多体系结构,尤其是 RISC 体系结构,在没有附加指令的情况下不保证该行为。

此外,编译器经常在函数中重新排序对内存的访问,在某些情况下,跨函数重新排序,并且需要具有适当屏障的原子类型来向编译器表明不需要这种行为。

最后,通常需要原子操作来逻辑更新变量的内容。例如,我可能想自动向变量加 1。在诸如 ARM 之类的加载-存储架构上,我无法使用 add 指令修改内存内容;我只能对寄存器进行算术运算。因此,原子加法是多条指令,通常由加载链接(加载内存位置)、寄存器上的加法操作以及条件存储(如果内存位置未更改则存储值)组成。如果有的话,还有一个重试循环。

这就是为什么需要原子操作并且原子操作在跨语言中通常有用的原因。因此,虽然人们可以在非 Rust 语言中使用非原子操作,但它们通常不会产生有用的结果,并且由于人们通常希望代码正确运行,因此原子操作对于正确性来说是可取的。Rust 的原子类型通过生成合适的指令来保证这种行为,因此可以在线程之间安全地共享。