std::memory_order for std::atomic:<T>:wait

std::memory_order for std::atomic<T>::wait

本文关键字:std gt wait lt atomic memory order for      更新时间:2023-10-16

根据cppreference,在C++20中,std::atomic<T>中有waitnotify_onenotify_all。看起来它们使std::atomic<T>可用作蒲团

我在问wait为什么接受std::memory_order作为参数。由于我总是需要检查从等待中唤醒是否不是伪造的,我将在相应的加载中指定内存顺序:

std::atomic<bool> x;
while (x.load(std::memory_order_acquire) == false)
{
x.wait(false, std::memory_order_acquire);
}

或者我应该指定std::memory_order_relaxed等待吗?是否存在wait之后没有load的情况?

同一对象上的所有原子操作都将始终具有单个顺序,并且单个线程内的顺序也包含在其中。也就是说,relaxed不能对同一线程中同一对象上的原子操作进行重新排序。

relaxed内存顺序是相对于除特定原子操作之外的其他内存操作的顺序。因此,relaxed可以检查等待本身,但当您想实际读取由不包含在原子值中的发布线程写入的数据时,您需要更强的内存顺序来确保它们的可见性。因此,如果有必要,外循环应该使用更合适的条件来获得可见性。

我将这个问题发布到了GitHub上,并得到了一个响应,即std::atomic::wait旨在通过逻辑在futex上实现,特别是为了屏蔽虚假唤醒。

因此,cppreference.com在这方面是错误的:

这些函数被允许虚假解锁,即由于值更改或通知以外的原因返回。

虽然循环在我的例子中是多余的,但我应该只使用:

std::atomic<bool> x;
x.wait(false, std::memory_order_acquire);