gpt4 book ai didi

c++ - std::condition_variable 内存写入可见性

转载 作者:行者123 更新时间:2023-12-04 14:05:41 27 4
gpt4 key购买 nike

std::condition_variable::notify_one()std::condition_variable::notify_all() 是否保证非原子内存写入当前线程之前该调用将在通知的线程中可见?

其他线程做:

{
std::unique_lock lock(mutex);
cv.wait(lock, []() { return values[threadIndex] != 0; });
// May a thread here see a zero value and therefore start to wait again?
}

主线程做:

fillData(values); // All values are zero and all threads wait() before calling this.
cv.notify_all(); // Do need some memory fence or lock before this
// to ensure that new non-zero values will be visible
// in other threads immediately after waking up?

notify_all() 不会存储一些原子值从而强制执行内存排序吗?我没有澄清。

UPD:根据 Superlokkus 的回答和 an answer here:我们必须获取锁以确保内存写入在其他线程中可见(内存传播),否则在我的例子中线程可能读取零值。

我还错过了这句话 here about condition_variable ,它专门回答了我的问题。在修改必须立即可见的情况下,即使是原子变量也必须在锁下修改。

Even if the shared variable is atomic, it must be modified under themutex in order to correctly publish the modification to the waitingthread.

最佳答案

我猜你混淆了所谓的原子值的内存排序和基于经典锁的同步机制。

当你有一个在线程之间共享的数据时,假设一个 int例如,一个线程不能简单地读取它而另一个线程可能同时写入它。否则我们就会发生数据竞争。

为了长期解决这个问题,我们使用了经典的基于锁的同步:这些线程至少共享一个互斥量和 int .要读取或写入任何线程必须首先持有锁,这意味着它们等待互斥量。构建互斥体是为了让它们可以同时发生。如果线程赢得互斥量,它可以更改或读取 int然后应该解锁它,这样其他人也可以读/写。使用像您使用的条件变量只是为了使“读者等待作者更改值”的模式更有效,他们被 cv 唤醒,而不是周期性地等待锁定、读取和解锁,这会被称为忙等待。

因此,因为您在等待互斥锁之后持有锁,或者在您的情况下,正确地(仍然需要互斥锁)等待条件变量,您可以更改 int .在作者能够写出新值之后,读者将阅读新值,而不是旧值。 更新:但是如果必须添加一件事,这也可能是造成混淆的原因:条件变量受所谓的虚假唤醒的影响。这意味着即使您写入没有通知任何线程,读取线程可能仍会唤醒,并且互斥量已锁定。所以你必须检查你的作者是否真的把你叫醒了,这通常是由作者通过更改另一个数据来通知这一点,或者通过使用你已经想分享的相同数据来完成的。 std::condition_variable::wait 的 lambda 参数重载只是为了让检查和返回 sleep 代码看起来更漂亮。根据你的问题现在不知道要不要用你values为了这份工作。

但是“主”线程的代码片段不正确或不完整:您没有在互斥锁上同步以更改 values .您必须为此持有锁,但可以在没有锁的情况下完成通知。

std::unique_lock lock(mutex);
fillData(values);
lock.unlock();
cv.notify_all();

但是这些基于互斥锁的模式有一些缺点并且速度很慢,一次只能有一个线程可以做某事。这就是所谓的原子,比如 std::atomic<int>开始发挥作用。它们可以在没有互斥量的情况下由多个线程并发地同时写入和读取。内存排序只是在那里需要考虑的事情,并且是对以有意义的方式使用其中多个内存或者不需要“写入后,我永远不会看到旧值”保证的情况的优化。然而,它的默认内存顺序为 memory_order_seq_cst你也会没事的。

关于c++ - std::condition_variable 内存写入可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68591370/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com