#include <atomic>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread> int main() {
constexpr size_t kLoopNum = 10;
std::mutex mtx;
std::condition_variable cv;
bool ready_flag{false}; std::thread thd_producer([&]() {
for (size_t i = 0; i < kLoopNum; i++) {
std::cout << "producer thread " << i << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100)); if (!ready_flag) {
std::unique_lock<std::mutex> lock;
ready_flag = true;
cv.notify_one();
}
}
}); std::thread thd_consumer([&]() {
for (size_t i = 0; i < kLoopNum; i++) {
std::cout << "consumer thread " << i << std::endl;
std::unique_lock<std::mutex> lock;
cv.wait(lock, [&]() {
return !ready_flag;
});
}
}); thd_producer.join();
thd_consumer.join();
}

输出信息:

producer thread 0
consumer thread 0
consumer thread 1
consumer thread 2
consumer thread 3
consumer thread 4
consumer thread 5
consumer thread 6
consumer thread 7
consumer thread 8
consumer thread 9
producer thread 1
producer thread 2
producer thread 3
producer thread 4
producer thread 5
producer thread 6
producer thread 7
producer thread 8
producer thread 9

使用解读

如下 a, b 用法等效

std::unique_lock <std::mutex> lck(mtx);
// cv.wait(lck, [&](){return ready;}); // (a)
while(!ready) cv.wait(lck); // (b)

条件变量ready必须位于lock中,以保证内存序

cpp reference: conditional_variable

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

Any thread that intends to wait on std::condition_variable has to

  1. acquire a std::unique_lockstd::mutex, on the same mutex as used to protect the shared variable
  2. either A

    2.1 check the condition, in case it was already updated and notified

    2.2 execute wait, wait_for, or wait_until. The wait operations atomically release the mutex and suspend the execution of the thread.

    2.3 When the condition variable is notified, a timeout expires, or a spurious wakeup occurs, the thread is awakened, and the mutex is atomically reacquired. The thread should then check the condition and resume waiting if the wake up was spurious.

    or B

    use the predicated overload of wait, wait_for, and wait_until, which takes care of the three steps above

C++11中的lock

  • std::unique_lock
  • std::lock_guard
  • std::scoped_lock
  • std::lock

C++11中的lock都属于资源自动管理(RAII)范畴。

unique_lock 在使用上比lock_guard更具有弹性,和 lock_guard 相比,unique_lock 主要的特色在于:

  1. unique_lock 不一定要拥有 mutex,所以可以透过 default constructor 建立出一个空的 unique_lock。
  2. unique_lock 虽然一样不可复制(non-copyable),但是它是可以转移的(movable)。所以,unique_lock 不但可以被函数回传,也可以放到 STL 的 container 里。
  3. 另外,unique_lock 也有提供 lock()、unlock() 等函数,可以用来加锁解锁mutex,也算是功能比较完整的地方。
  4. unique_lock本身还可以用于std::lock参数,因为其具备lock、unlock、try_lock成员函数,这些函数不仅完成针对mutex的操作还要更新mutex的状态。

conditional_variable的notidy

  1. cv.notify_one
  2. cv.notify_all
  3. std::notify_all_at_thread_exit(...)

参考

(C++) 笔记 C++11 std::mutex std::condition_variable 的使用的更多相关文章

  1. 基于std::mutex std::lock_guard std::condition_variable 和std::async实现的简单同步队列

    C++多线程编程中通常会对共享的数据进行写保护,以防止多线程在对共享数据成员进行读写时造成资源争抢导致程序出现未定义的行为.通常的做法是在修改共享数据成员的时候进行加锁--mutex.在使用锁的时候通 ...

  2. 转 C++11 并发指南std::condition_variable详解

    之前看过,但是一直没有怎么用就忘了,转一篇别人的文字记录下来 本文将介绍 C++11 标准中 <condition_variable> 头文件里面的类和相关函数. <conditio ...

  3. 【C/C++开发】C++11 并发指南三(std::mutex 详解)

    本系列文章主要介绍 C++11 并发编程,计划分为 9 章介绍 C++11 的并发和多线程编程,分别如下: C++11 并发指南一(C++11 多线程初探)(本章计划 1-2 篇,已完成 1 篇) C ...

  4. C++11 并发指南三(std::mutex 详解)

    上一篇<C++11 并发指南二(std::thread 详解)>中主要讲到了 std::thread 的一些用法,并给出了两个小例子,本文将介绍 std::mutex 的用法. Mutex ...

  5. C++11并发——多线程std::mutex (二)

    https://www.cnblogs.com/haippy/p/3237213.html Mutex 又称互斥量,C++ 11中与 Mutex 相关的类(包括锁类型)和函数都声明在 <mute ...

  6. C++11 并发指南三(std::mutex 详解)(转)

    转自:http://www.cnblogs.com/haippy/p/3237213.html 上一篇<C++11 并发指南二(std::thread 详解)>中主要讲到了 std::th ...

  7. C++11并发——多线程std::thread (一)

    https://www.cnblogs.com/haippy/p/3284540.html 与 C++11 多线程相关的头文件 C++11 新标准中引入了四个头文件来支持多线程编程,他们分别是< ...

  8. C++ 11 多线程下std::unique_lock与std::lock_guard的区别和用法

    这里主要介绍std::unique_lock与std::lock_guard的区别用法 先说简单的 一.std::lock_guard的用法 std::lock_guard其实就是简单的RAII封装, ...

  9. C++11:基于std::queue和std::mutex构建一个线程安全的队列

    C++11:基于std::queue和std::mutex构建一个线程安全的队列 C++中的模板std::queue提供了一个队列容器,但这个容器并不是线程安全的,如果在多线程环境下使用队列,它是不能 ...

  10. C++11并发之std::mutex

    知识链接: C++11并发之std::thread   本文概要: 1. 头文件. 2.std::mutex. 3.std::recursive_mutex. 4.std::time_mutex. 5 ...

随机推荐

  1. Mac隔空投送功能

    使用mac 或iphone 的隔空投送功能可以互发文件,亲测可用 具体可以看mac的文档 需要注意的是: 如果是mac传iphone,iphone会显示你需要存储文件的地方,比如选择在文稿中.然后在文 ...

  2. Windows 客户端802.1x的一些设置

    802.1x作为网络准入的验证,自然有很多好处.但是在实施过程中也遇到了些小问题.我在这里记录下来,希望对大家有帮助,遇到问题的时候能有个参考. 基于用户验证的方式,当用户修改了密码后,验证失败.此时 ...

  3. PHP函数小工具

    PHP检测IP是否内网地址.保留地址 /** * @param string $ip 被检测的IP * @return bool 是否内网或者保留IP */ public function isInt ...

  4. Mybatis 一级缓存和二级缓存原理区别 (图文详解)

    Java面试经常问到Mybatis一级缓存和二级缓存,今天就给大家重点详解Mybatis一级缓存和二级缓存原理与区别@mikechen Mybatis缓存 缓存就是内存中的数据,常常来自对数据库查询结 ...

  5. 第六章:Django 综合篇 - 10:消息框架 message

    在网页应用中,我们经常需要在处理完表单或其它类型的用户输入后,显示一个通知信息给用户. 对于这个需求,Django提供了基于Cookie或者会话的消息框架messages,无论是匿名用户还是认证的用户 ...

  6. MySQL 的七种日志总结

    文章转载自:https://mp.weixin.qq.com/s/ewv7HskHvH3O7kFyOmoqgw 一.MySQL 日志分类 日志类别 说明 备注 错误日志 错误日志记录了当MySQL启动 ...

  7. 使用Jumpserver堡垒机管理MySQL应用

    第一步,添加系统用户 资产管理,系统用户,创建<数据库协议>MySQL 用户名和密码填写实际可以访问数据库的用户名和密码 第二步,添加应用 应用管理,数据库 主机和端口填写可以访问数据库的 ...

  8. 《Spatial-Spectral T ransformer for Hyperspectral Image Classification》论文笔记

    论文题目<Spatial-Spectral T ransformer for Hyperspectral Image Classification> 论文作者:Xin He 1 , Yus ...

  9. SQL通用语法和SQL分类

    SQL通用语法 1.SQL 语句可以单行或多行书写,以分号结尾 2.可使用空格和缩进来增强语句的可读性 3.MySQL 数据库的SQL语句不区分大小写,关键字建议使用大写 4.3种注释 单行注释: - ...

  10. C++面向对象编程之复合、委托和继承

    1.复合,表示has a template <typename T> calss A{ protected: B<T> c; } 这里表示 A 里面有一个 B,A 可以调用 B ...