c++11多线程编程(七):条件变量说明

条件变量
条件变量是一种用于在2个线程之间进行信令的事件,一个线程可以等待它得到信号,其他的线程可以给它发信号。
在c++11中,条件变量需要头文件:
#include <condition_variable>

同时,条件变量还需要一个mutex锁


条件变量实际上是如何运作的

  ·线程1调用等待条件变量,内部获取mutex互斥锁并检查是否满足条件;
  ·如果没有,则释放锁,并等待条件变量得到发出的信号(线程被阻塞),条件变量的wait()函数以原子方式提供这两个操作;
  ·另一个线程,如线程2,当满足条件时,向条件变量发信号;
  ·一旦线程1正等待其恢复的条件变量发出信号,线程1便获取互斥锁,并检查与条件变量相关关联的条件是否满足,或者是否是一个上级调用,如果多个线程正在等待,那么      notify_one将只解锁一个线程;
  ·如果是一个上级调用,那么它再次调用wait()函数。

条件变量的主要成员函数是:
Wait()

它使得当前线程阻塞,直到条件变量得到信号或发生虚假唤醒;
它原子性地释放附加的mutex,阻塞当前线程,并将其添加到等待当前条件变量对象的线程列表中,当某线程在同样的条件变量上调用notify_one() 或者 notify_all(),线程将被解除阻塞;
这种行为也可能是虚假的,因此,解除阻塞后,需要再次检查条件;
一个回调函数会传给该函数,调用它来检查其是否是虚假调用,还是确实满足了真实条件;
当线程解除阻塞后,wait()函数获取mutex锁,并检查条件是否满足,如果条件不满足,则再次原子性地释放附加的mutex,阻塞当前线程,并将其添加到等待当前条件变量对象的线程列表中。

notify_one()
如果所有线程都在等待相同的条件变量对象,那么notify_one会取消阻塞其中一个等待线程。

notify_all()

如果所有线程都在等待相同的条件变量对象,那么notify_all会取消阻塞所有的等待线程。
如何处理第六节讨论的带有条件变量的多线程情景呢?

c++11多线程编程(六):事件处理 (这节中,我们没有用事件处理来解决问题)


问题场景
我们创建一个基于网络的应用程序,处理如下的任务:

1、与处理器进行一些握手操作;
2、从xml文件load数据;
3、处理从xml文件load的数据.
可以发现,任务1不依赖其他的任务,而任务3则依赖于任务2,这意味着任务1和任务2可以由不同的线程并行运行,以提升程序性能。
因此,让我们将其分解成一个多线程的应用程序。
线程1的任务是:
·与服务器进行握手操作
·等待线程2从xml获取的数据
·处理从xml获取的数据
线程2的任务是:
·从xml获取数据
·通知另一个线程,即等待消息

实现代码如下:

#include <iostream>
#include <thread>
#include <functional>
#include <mutex>
#include <condition_variable>
using namespace std::placeholders;

class Application {
  std::mutex m_mutex;
  std::condition_variable m_condVar;
  bool m_bDataLoaded;
 public:
  Application() {
    m_bDataLoaded = false;
  }

  void loadData() {
    //使该线程sleep 1秒
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    std::cout << "Loading Data from XML" << std::endl;

    //锁定数据
    std::lock_guard<std::mutex> guard(m_mutex);

    //flag设为true,表明数据已加载
    m_bDataLoaded = true;

    //通知条件变量
    m_condVar.notify_one();
  }

  bool isDataLoaded() {
    return m_bDataLoaded;
  }

  void mainTask() {
    std::cout << "Do some handshaking" << std::endl;

    //获取锁
    std::unique_lock<std::mutex> mlock(m_mutex);

    //开始等待条件变量得到信号
    //wait()将在内部释放锁,并使线程阻塞
    //一旦条件变量发出信号,则恢复线程并再次获取锁
    //然后检测条件是否满足,如果条件满足,则继续,否则再次进入wait
    m_condVar.wait(mlock, std::bind(&Application::isDataLoaded, this));
    std::cout << "Do Processing On loaded Data" << std::endl;
  }
};

int main() {
  Application app;
  std::thread thread_1(&Application::mainTask, &app);
  std::thread thread_2(&Application::loadData, &app);
  thread_2.join();
  thread_1.join();

  return 0;
}



  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值