• 并发与多线程(5) 条件变量 condition_variable


    一、简介

    案例情景:

    A线程:等待一个条件满足

    B线程:专门给消息队列中加入消息

    引入一个新的知识点: condition_variable

    condition_variable的功能:实际上是一个类,是一个和条件相关的类,说白了就是等待一个条件的达成, 这个类必须和互斥量(mutex )来配合工作,用的时候要生产这个类的对象。

    二、condition_variable.wait()的使用

               1、 wait  是在等一个东西,是一个成员函数如果 第二个参数(【this 】{}lambdaba表达式) 里面的返回值是false ,那么wait() 将解锁互斥量,并堵塞到这里,如果返回的是true ,则直接返回
              2、  那什么时候解锁呢?  阻塞到其他线程调用 notifty_one() 成员函数的时候为止,也还是说  wait 和notifty_one 是一对搭档
                3、如果wait() 成员函数中没有第二个参数my_c_v.wait(mylock2),则表示的是第二个参数返回的就是false

                  4、当其他线程用notfity_one()唤醒本(这个阻塞)wait() 将解锁互斥量,那这个边开始干活,然后wait() 不断尝试去重新获得这个锁,这个会卡到这里,就会执行b
                 b:  b1:如果wait() 有第二个参数,就判断这lambda 表达式,如果返回的是false,就讲wait 解锁,又等待再次唤醒
                b2:lambda 表达式,如果返回的是true,此时锁还上锁定状态,就会接着走下面的流程

    1. #if 1
    2. class A
    3. {
    4. public:
    5. // 吧收到的消息 入到一个队列当中
    6. void inMsgRecvQueue()
    7. {
    8. for (size_t i = 0; i < 10000; i++)
    9. {
    10. cout << "inMsgRecvQueue() 执行,插入一个元素 " << i << endl;
    11. unique_lock mylock2(my_mutex);
    12. my_c_v.notify_one(); // 唤醒
    13. msgRecvQueue.push_back(i);
    14. }
    15. }
    16. // 另外一个线程
    17. void getMsgRecvQueue()
    18. {
    19. int cmd = 0;
    20. while (1)
    21. {
    22. unique_lock mylock2(my_mutex);
    23. // wait 是在等一个东西,是一个成员函数如果 【this 】{} 这个里面的返回值是false ,那么wait() 将解锁互斥量,并堵塞到这里,如果返回的是true ,则直接返回
    24. // 那什么时候解锁呢? 阻塞到其他线程调用 notifty_one() 成员函数的时候为止,也还是说 wait 和notifty_one 是一对搭档
    25. // 如果wait() 成员函数中没有第二个参数my_c_v.wait(mylock2),则表示的是第二个参数返回的就是false
    26. // 当其他线程用notfity_one()唤醒本(这个阻塞)wait() 将解锁互斥量,那这个边开始干活,然后wait() 不断尝试去重新获得这个锁,这个会卡到这里,就会执行b
    27. // b: b1:如果wait() 有第二个参数,就判断这lambda 表达式,如果返回的是false,就讲wait 解锁,又等待再次唤醒
    28. // b2:lambda 表达式,如果返回的是true,此时锁还上锁定状态,就会接着走下面的流程
    29. my_c_v.wait(mylock2, [this]
    30. { // this 表示的是这个条件变量
    31. if (msgRecvQueue.empty() == false)
    32. return true;
    33. return false;
    34. });
    35. cmd = msgRecvQueue.front();
    36. msgRecvQueue.pop_front();
    37. mylock2.unlock();
    38. cout << "msgRecvQueue 取出一个cmd !"<< cmd<
    39. }
    40. }
    41. private:
    42. list<int> msgRecvQueue;
    43. mutex my_mutex; // 创建一个互斥量
    44. condition_variable my_c_v; // 生产一个条件对象
    45. };
    46. int main()
    47. {
    48. A a;
    49. thread mythread(&A::getMsgRecvQueue, &a); // 第二对象是 &
    50. thread mythread2(&A::inMsgRecvQueue, &a);
    51. mythread.join();
    52. mythread2.join();
    53. cout << "Hello World!\n";
    54. }
    55. #endif

  • 相关阅读:
    SPDK——每秒8千万次I/O性能实现
    构建工具vite/webpack
    C++ template模板学习
    安装pandas==0.22.0时的问题
    Windows编程技术之运行单一实例
    面试突击55:delete、drop、truncate有什么区别?
    VoLTE端到端业务详解 | 用户标识类
    python 爱心代码
    循环赛-(单循环)
    电子证据的固定方法研究
  • 原文地址:https://blog.csdn.net/weixin_39354845/article/details/127613389