我有以下代码在一个线程上执行(用c++ 20编写):
std::atomic_bool is_ready{};
void SetReady() {
is_ready.store(true, std::memory_order_release);
is_ready.notify_all();
}
其他线程执行下面列出的文本:
void Wait() {
is_ready.wait(false, std::memory_order_acquire);
}
据我所知,释放内存顺序并不能保证位于它之后的操作不会被编译器重新排序。那么,我可以将notify_all()
放置在store()
之后并释放内存吗?安全吗?只是我有一些想法,store()
可能在notify_all()
之前排序,因此可能不会重新排序。
内存顺序在这里是无关的。它们只影响以外的内存访问的顺序,而不影响原子本身。
编译器不能在任何情况下将notify_all
调用重排在store之前,因为notify_all
被指定为唤醒原子上所有等待有资格被解除阻塞的操作。
这取决于在原子的全局修改顺序中,发生的最后一个存储是否在之前,对notify_all
的调用顺序是否在等待线程阻塞时观察到的存储之后。
在您所显示的代码中,true
存储在notify_all
调用之前排序(在同一线程中),这意味着存储发生在调用之前,但是如果交换行,那么情况就不再是这样了。
将notify_all
移到store之前可能会改变等待操作的集合,这些操作有资格被解除阻塞。
如果编译器被允许这样做,那么等待/通知机制将是相当无用的。这与同一线程中对同一原子的其他操作(或者实际上是同一线程中对同一存储位置的任何操作)也是一样的。编译器也不能重新排序。
所以,是的,它是安全的,Wait
线程不会永远等待。(我假设初始化std::atomic_bool is_ready{};
是在显示的线程函数开始执行之前发生的)