首页 > 其他分享 >7. 等待一个事件

7. 等待一个事件

时间:2023-01-10 17:13:39浏览次数:34  
标签:一个 等待 que 事件 variable 线程 data condition wait

等待一个事件

在多线程开发中,当一个线程的运行条件是另外一个线程的运算结果的时间,等待线程通常有几种处理方法1. 循环查询,知道满足条件为止 2. 休眠一个固定的时间,然后查询条件,当不满足的时候再继续休眠相同时间,知道下一次查询满足条件 3. 使用条件变量
下面分别对后两种方法进行阐述


  1. 休眠固定时间
    使用std::sleep_for()进行周期性的间歇
    bool flag
    mutex m;
    void wait_for(){
      unique_lock<mutex>uloc(m);
      while(!flag){
        uloc.unlock();
    	this_thread::sleep_for(chrono::nilliseconds(100));
    	uloc.lock();
      }
    }
    

这种方法的优缺点也很直觉,优点:代码简单易懂,缺点:睡眠的时间难以掌握


  1. 使用条件变量
    C++标准库对于条件变量有两套实现:std::condition_variablestd::condition_variable_any两个实现都包含在头文件<condition_variable>中,两者都需要一个互斥量才能工作,前者仅能和mutex一起工作,而后者可以和各种互斥量进行工作,因为后者更加通用,所以导致从体积,性能,以及系统资源等方面有着更大的消耗,在一般的开发过程中,前者为首选类型,当系统对于灵活性有着硬性要求的时候才考虑后者
    下面的代码展示了condition_variable的基本使用:
    mutex m;
    queue<int>que;
    condition_variable que_cond;
    void data_prepare_thread(){
      while(more_prepare_data()){
        auto data = prepare_data();
        lock_guard<mutex>loc(m);
        que.push(data);
        que_cond.notify_once();
      }
    }
    void data_process_thread(){
      while(true){
        unique_lock<mutex>lk(m);
        que_cond.wait(lk,[&que](){return !que.empty();});
        auto data = que.front();
        que.pop();
        lk.unlock();
        process(data);
        if(is_lask_chunk(data))
          break;
      }
    }
    

对于生产者,首先对共享资源上锁,然后将准备的数据添加进入共享资源,最后调用condition_variable中的notify_one()成员函数对等待的线程进行通知
对于消费者,首先对共享资源上锁,调用condition_variable中的wait方法,wait首先回去检查第二参数是否满足条件,如果满足则继续持有锁,进行下面的操作,如果不满足条件则释放锁,然后置于阻塞或者等待状态,知道进程被唤醒。
注意,不一定是另一个线程调用notify的时候wait状态才会被唤醒,某些条件下wait状态的线程也会被唤醒,这就是所谓的伪唤醒,因此判断条件的合适性显得尤为重要。

标签:一个,等待,que,事件,variable,线程,data,condition,wait
From: https://www.cnblogs.com/hhyandcpp/p/17040786.html

相关文章