C ++ 11多线程–第7部分:条件变量介绍

翻译来自:C++11 Multithreading – Part 7: Condition Variables Explained
在本文中,我们将通过示例讨论C ++ 11多线程中条件变量的用法。

**

条件变量

**
条件变量是一种事件,用于在两个或多个线程之间进行信号传递。一个或多个线程可以等待它发出信号,而另一个线程可以发出信号。

C ++ 11中的条件变量所需的头文件是,

#include <condition_variable>

需要互斥锁以及条件变量。
条件变量如何实际起作用

线程1调用wait on condition变量,该变量在内部获取互斥量并检查是否满足所需条件。
如果不是,则释放锁定并等待条件变量得到信号(线程被阻塞)。条件变量的wait()函数以原子方式提供这两种操作。
当满足条件时,另一个线程(如线程2)会发出条件变量的信号
一旦条件变量得到信号,正在等待它的线程1恢复。然后,它再次获取互斥锁,并检查与条件变量关联的条件是否真正满足或是否为上级调用。如果有多个线程在等待,那么notify_one将仅解除阻塞一个线程。
如果是上级调用,则再次调用wait()函数。
std :: condition_variable的主要成员函数是:
Wait()
它使当前线程阻塞,直到信号通知条件变量或发生虚假唤醒为止。

它以原子方式释放附加的互斥锁,阻塞当前线程,并将其添加到等待当前条件变量对象的线程列表中。当某些线程在同一条件变量对象上调用notify_one()或notify_all()时,该线程将被解除阻塞。它也可能会被虚假地解除阻塞,因此,每次解除阻塞后,都需要再次检查条件。

回调将作为参数传递给此函数,然后将调用该回调以检查它是否是虚假调用或是否实际满足条件。

线程解锁后,

wait()函数重新获取互斥锁,并检查是否满足实际条件。如果不满足条件,那么它将再次自动释放附加的互斥锁,阻塞当前线程,并将其添加到等待当前条件变量对象的线程列表中。

notify_one()

如果有任何线程在同一条件变量对象上等待,则notify_one解除阻塞其中一个等待线程。

notify_all()

如果有任何线程在同一条件变量对象上等待,则notify_all取消阻止所有正在等待的线程。

让我们看看如何使用条件变量(即条件变量)处理先前讨论的多线程方案
多线程中需要事件处理 (在本文中,我们没有事件处理就解决了问题)
问题场景

假设我们正在构建一个基于网络的应用程序。此应用程序执行以下任务,

  1. 与服务器进行一些握手
  2. 从XML文件加载数据
  3. 对从XML加载的数据进行处理。

如我们所见,任务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()
  {
   // Make This Thread sleep for 1 Second
   std::this_thread::sleep_for(std::chrono::milliseconds(1000));
   std::cout<<"Loading Data from XML"<<std::endl;
   // Lock The Data structure
   std::lock_guard<std::mutex> guard(m_mutex);
   // Set the flag to true, means data is loaded
   m_bDataLoaded = true;
   // Notify the condition variable
   m_condVar.notify_one();
  }
  bool isDataLoaded()
  {
    return m_bDataLoaded;
  }
  void mainTask()
  {
    std::cout<<"Do Some Handshaking"<<std::endl;
    // Acquire the lock
    std::unique_lock<std::mutex> mlock(m_mutex);
    // Start waiting for the Condition Variable to get signaled
    // Wait() will internally release the lock and make the thread to block
    // As soon as condition variable get signaled, resume the thread and
    // again acquire the lock. Then check if condition is met or not
    // If condition is met then continue else again go in 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值