std::memory_order 对于 std::atomic<T>:: 等待
std::memory_order for std::atomic<T>::wait
根据cppreference,在C++20中std::atomic<T>
中有wait
、notify_one
、notify_all
。看起来他们让 std::atomic<T>
可以用作 futex。
我在问为什么 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,并得到 a response std::atomic::wait 旨在在具有逻辑的 futex 上实现,特别是为了掩盖虚假唤醒.
所以,cppreference.com 是错误的:
These functions are allowed to unblock spuriously, i.e. return due to reasons other than value change or notification.
while 循环在我的示例中是多余的,我应该只使用:
std::atomic<bool> x;
x.wait(false, std::memory_order_acquire);
根据cppreference,在C++20中std::atomic<T>
中有wait
、notify_one
、notify_all
。看起来他们让 std::atomic<T>
可以用作 futex。
我在问为什么 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,并得到 a response std::atomic::wait 旨在在具有逻辑的 futex 上实现,特别是为了掩盖虚假唤醒.
所以,cppreference.com 是错误的:
These functions are allowed to unblock spuriously, i.e. return due to reasons other than value change or notification.
while 循环在我的示例中是多余的,我应该只使用:
std::atomic<bool> x;
x.wait(false, std::memory_order_acquire);