- 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/
我正在开发一个小型图书馆,我需要做的一件事是让访问者访问一些数据并返回结果。 在一些较旧的 C++ 代码中,访问者需要声明一个 typedef return_type .例如,boost::stati
我正在尝试使用std:map类型的键和值制作std::any Visual Studio 2017 std::map m("lastname", "Ivanov"); std::cout (m["la
我已经在 C++ 的 map 中声明了一个集合为 std::map> .如何循环访问或打印设定值? 最佳答案 如果你知道如何迭代 std::map或 std::set单独地,您应该可以毫无问题地组合迭
如何循环? 我已经试过了: //----- code std::vector >::iterator it; for ( it = users.begin(); it != users.end();
我有两个用例。 A.我想同步访问两个线程的队列。 B.我想同步两个线程对队列的访问并使用条件变量,因为其中一个线程将等待另一个线程将内容存储到队列中。 对于用例 A,我看到了使用 std::lock_
我正在查看这两种类型特征的文档,但不确定有什么区别。我不是语言律师,但据我所知,它们都适用于“memcpy-able”类型。 它们可以互换使用吗? 最佳答案 不,这些术语不能互换使用。这两个术语都表示
我有以下测试代码,其中有一个参数 fS,它是 ofstream 的容器: #include #include #include #include int
这是这个问题的延续 c++ function ptr in unorderer_map, compile time error 我试图使用 std::function 而不是函数指针,并且只有当函数是
std::unordered_map str_bool_map = { {"a", true}, {"b", false}, {"c", true} }; 我们可以在此映射上使
我有以下对象 std::vector> vectorList; 然后我添加到这个使用 std::vector vec_tmp; vec_tmp.push_back(strDRG); vec_tmp.p
为什么 std::initializer_list不支持std::get<> , std::tuple_size和 std::tuple_element ?在constexpr中用得很多现在的表达式,
我有一个像这样定义的变量 auto drum = std::make_tuple ( std::make_tuple ( 0.3f , Ex
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
问题 我正在尝试将 lambda 闭包传递给 std::thread,它使用任意封闭参数调用任意封闭函数。 template std::thread timed_thread(Function&& f
我想创建一个模板类,可以容纳容器和容器的任意组合。例如,std::vector或 std::map ,例如。 我尝试了很多组合,但我必须承认模板的复杂性让我不知所措。我编译的关闭是这样的: templ
我有一个 std::vector>我将其分配给相同类型的第二个 vector 。 我收到这个编译器错误: /opt/gcc-8.2.0/include/c++/8.2.0/bits/stl_algob
有时候,我们有一个工厂可以生成一个 std::unique_ptr vector ,后来我们想在类/线程/你命名的之间共享这些指针。因此,最好改用 std::shared_ptr 。当然有一种方法可以
这个问题在这里已经有了答案: Sorting a vector of custom objects (14 个答案) 关闭 6 年前。 我创建了一个 vector vector ,我想根据我定义的参
我有三个类(class)成员: public: std::vector > getObjects(); std::vector > getObjects() const; privat
我是一名优秀的程序员,十分优秀!