1

这是关于 Rust 异步生态系统内的内存排序保证的一个相当基本的问题。但是,我似乎在任何地方都找不到明确的答案。

C++ 内存排序从基于线程的角度指定内存排序:

发布-获取排序

如果线程 A 中的原子存储标记为 memory_order_release,并且线程 B 中来自同一变量的原子加载标记为 memory_order_acquire,则从线程的角度来看,在原子存储之前发生的所有内存写入(非原子和宽松原子) A,在线程 B 中成为可见的副作用。也就是说,一旦原子加载完成,线程 B 保证可以看到线程 A 写入内存的所有内容。

各种 Rust 异步执行器支持跨线程移动任务.await。一个自然的场景是:

  1. Relaxed任务 A 位于线程 1 并在变量 处执行存储x
  2. 任务 A.await命中
  3. 任务 A 被移动到线程 2 并被唤醒。Release然后在变量处执行存储y
  4. 任务 B 位于线程 3 并在变量处执行Acquire加载y

问题是:线程 1 的存储是否保证在加载Relaxed后在任务 B 中可见?Acquire例如,如果线程 3 的任务 B之后Relaxed在变量处执行了负载x,是否可以保证任务 A 的副作用是可见的?

这应该取决于每个异步执行器的任务调度程序中同步机制的实现。任何熟悉它们的人都会受到赞赏。

4

1 回答 1

0

Tokio 维护者的评论

当任务从一个线程移动到另一个线程时,.await 之前和之后的事物之间存在同步关系。根据具体情况,同步来自互斥锁或使用获取和释放语义的原子。

在 C++ 内存规范中,synchronizse-with保证线程间发生之前。因此,至少在 Tokio 中,从某.await一点上忽略内存排序影响应该是安全的。

于 2022-02-09T11:57:22.223 回答