gpt4 book ai didi

multithreading - 既然 U32 已经实现了同步,为什么还要在 Rust 中使用 AtomicU32?

转载 作者:行者123 更新时间:2023-12-03 11:34:07 25 4
gpt4 key购买 nike

std::sync::atomic模块包含许多原始类型的原子变体,目的是这些类型现在是线程安全的。然而,所有对应于原子类型的原语都已经实现了Send。和 Sync ,因此应该已经是线程安全的。 Atomic 背后的原因是什么?类型?

最佳答案

通常,非原子整数可以安全地跨线程共享,因为它们是不可变的。如果您尝试修改该值,则在大多数情况下会隐式创建一个新值,因为它们是 Copy .但是,共享对 u32 的可变引用并不安全。跨线程(或对同一值具有可变和不可变引用),这实际上意味着您将无法修改变量并让另一个线程看到结果。原子类型具有一些使其安全的附加行为。
在更一般的情况下,使用非原子操作并不能保证在一个线程中所做的更改将在另一个线程中可见。许多架构,尤其是 RISC 架构,在没有额外指令的情况下不能保证这种行为。
此外,编译器经常对函数中的内存访问进行重新排序,在某些情况下,还需要跨函数重新排序,并且需要具有适当屏障的原子类型来向编译器指示不需要这种行为。
最后,通常需要原子操作来逻辑更新变量的内容。例如,我可能想以原子方式将 1 添加到变量中。在 ARM 等加载存储架构上,我无法使用 add 指令修改内存内容;我只能对寄存器进行算术运算。因此,原子加法是多条指令,通常包括一个加载链接,它加载一个内存位置,寄存器上的加法操作,然后是一个存储条件,如果内存位置没有改变,它存储值。如果有的话,还有一个循环可以重试。
这就是为什么需要原子操作并且通常跨语言有用的原因。因此,虽然可以在非 Rust 语言中使用非原子操作,但它们通常不会产生有用的结果,而且由于人们通常希望自己的代码能够正确运行,原子操作对于正确性来说是可取的。 Rust 的原子类型通过生成合适的指令来保证这种行为,因此可以安全地跨线程共享。

关于multithreading - 既然 U32 已经实现了同步,为什么还要在 Rust 中使用 AtomicU32?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62905764/

25 4 0