- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
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/
此代码是实际项目代码的简化。主线程创建工作线程并使用 std::condition_variable 等待工作线程真正启动。在下面的代码中,std::condition_variable 在 curr
reference I'm using用以下方式解释这两者: wait_for "阻塞当前线程,直到条件变量被唤醒或在指定的超时时间之后" wait_until "阻塞当前线程,直到条件变量被唤醒或到
标题问题的较长版本是: On my machine, sizeof(std::condition_variable) is 72 bytes.What are these 72 bytes used
假设我有这样的事情: bool signalled = false; std::condition_variable cv; void thread1() { while (true) {
我在下面的代码中遇到错误。 recursive_mutex m_RecurMutex; condition_variable cond; unique_lock lock(m_RecurMutex);
这是什么: bool ready; boost::mutex mutex; boost::condition_variable cond; boost::unique_lock lock(mutex)
这个问题是关于condition_variable.wait()的功能。我认为它可能没有锁定 unique_lock当它被通知时立即。让我展示一下我的代码,您会更好地理解我的测试。 注意:编译器 g+
我是条件变量的新手,我想知道为什么计数器变量等于 99 之后的这段代码块?删除for循环并改用“counter += 99”使代码工作,它与sleep_for有什么关系吗?感谢您的帮助:) #incl
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
似乎 condition_variable notify_one 并不总是按应有的方式工作。 struct Task { std::mutex mutex; std::conditio
条件变量可用于向其他线程发出信号,表明发生了某些事情: mutex m; condition_variable cv; thread t1([&cv]{ // processing .
没有 std::condition_variable 的应用程序: #include #include #include #include #include #include std::m
首先是我的代码,让我的解释更清楚: struct Foo { std::condition_variable cv; }; static Foo* foo; // dynamically cr
std::condition_variable::notify_one() 或 std::condition_variable::notify_all() 是否保证非原子内存写入当前线程之前该调用将在
我目前正在对并发队列进行编程,同时学习如何使用C++ 11的多线程功能。 当使用者调用dequeue()函数且队列中没有任何条目时,该函数应等待,直到另一个线程调用enqueue()为止。我正在为此使
我有一个关于notify_one函数的问题。在下面的代码中, #include #include #include #include #include std::condition_vari
我有一个以下类(class)- boost::condition_varaible cond_; 当我尝试编译时- [rmitra @ butterfly boost] $ make EXE = th
这是一个小代码段 request_ptr pop() { request_ptr rp; std::unique_lock lock(cv_mtx); auto time =
假设我有一个包含std::queue的ThreadQueue类,并且我将每个std::ref的实例传递给线程。进一步假设,线程1(主线程)创建并保存ThreadQueue对象,并将消息倒入其中,第二个
我有课,用 queue的 std::function成员和方法 Push和 Pop . 我要实现加法PushAndWaitUntilExecuted .当你有一个时很容易consumer-thread
我是一名优秀的程序员,十分优秀!