C++11并发与多线程笔记(8) condition_variable、wait、notify_one、notify_all

本文介绍了C++11中的condition_variable、wait、notify_one和notify_all在并发编程中的使用,包括它们的作用、方法和应用场景,以及如何避免因多线程同步问题导致的效率问题。
摘要由CSDN通过智能技术生成

1、条件变量condition_variable、wait、notify_one、notify_all

1.1 std::condition_variable

实际上是一个,是一个和条件相关的类,说白了就是等待一个条件达成。

1.2 wait()

  1. wait()只有一个参数(相当于第二个参数为true)
    void wait( std::unique_lock<std::mutex>& lock )

    先解锁之前获得的互斥量mutex,然后阻塞当前的执行线程。把当前线程添加到等待线程列表中,该线程会持续阻塞直到被 ** notify_one()** 唤醒。被唤醒后,该thread会尝试重新获取互斥量mutex,获取到mutex后执行后面的动作。

  2. wait()有两个参数
    void wait( std::unique_lock<std::mutex>& lock, Predicate pred )
    设置了第二个参数 Predicate, 只有当pred为false时,wait才会阻塞当前线程。这情况下,线程被唤醒后,先获取mutex,再次判断pred的值。如果pred为false,则会释放mutex并重新阻塞在wait

wait() 效果就是把锁释放并阻塞,以便于其他人去获取,不然条件不满足时,一遍遍去询问,太浪费时间。

1.3 notify_one()

随机唤醒一个等待的线程

notify_one() 唤醒一个线程不一定能成功,如果要唤醒的线程不在wait()处等待,将没有唤醒效果。

1.4 notify_all()

唤醒所有等待的线程

#include <iostream>
#include <thread>
#include <mutex>
#include <list>
using namespace std;

list<int> test_list;
mutex myMutex1;//创建一个互斥量

condition_variable my_cond;//生成一个条件变量对象
void in_list() {
    for (int num = 0; num < 100000; num++) {
        {
            cout << "插入数据:" << num << endl;
            unique_lock<mutex> myUniLock(myMutex1);
            //操作事务
            test_list.push_back(num);
            my_cond.notify_one();//我们尝试把wait()的线程唤醒,执行完这行,那么out_list()里边的wait就会被唤醒
        }
    }
}

void out_list() {
    int command = 0;
    while (true) {
        unique_lock<mutex> myUniLock(myMutex1);
        //如果第二个参数lambda表达式返回值是false,那么wait()将解锁互斥量,并堵塞到本行,
        my_cond.wait(myUniLock, [=] {//一个lambda就是一个可调用的对象(函数)
            if (!test_list.empty())
                return true;
            return false;
         });
        //流程只要走到这里来,这个互斥锁一定是锁着的
        command= test_list.front();//返回第一个元素,但不检查元素是否存在
        test_list.pop_front();//移除第一个元素,但不返回
        myUniLock.unlock();//可以提前解锁,以免锁住太长时间
        //执行其它非共享数据业务
        cout << "out_list()执行,取出一个元素" << command << endl;
    }
}
int main()
{
    thread in_thread(in_list);
    thread out_thread(out_list);
    out_thread.join();
    in_thread.join();
    cout << "I love China!" << endl;
    return 0;
}

2、深入思考

上面的代码可能导致出现一种情况:
因为out_list()与in_list()并不是一对一执行的,所以当程序循环执行很多次以后,可能在test_list中已经有了很多消息,但是,out_list还是被唤醒一次只处理一条数据。这时可以考虑把out_list多执行几次,或者对in_list进行限流

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值