C++11——多线程编程6

翻译来自:https://thispointer.com//c11-multithreading-part-6-need-of-event-handling/

在这个文章中 我们将讨论多线程中事件处理的必要性

有时候 线程需要等待某件事情发生 比如条件为真或者是任务通过另外一个线程被完成了

比如

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

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

正如我们所见,Task 1 不依赖于任何其他 Task,而 Task 3 依赖于 Task 2。因此,这意味着 Task 1 和 Task 2 可以由不同的线程并行运行,以提高应用程序的性能。

所以,让我们把它分解成一个多线程应用程序,

现在,它包括两个线程,

线程 1 的职责是,

  • 与服务器执行一些握手。
  • 等待线程 2 从 XML 加载数据
  • 对从 XML 加载的数据进行处理。

线程 2 的职责是,

  • 从 XML 加载数据
  • 通知另一个线程,即等待消息

 

 

 

在上面,线程 1 执行一些操作,然后等待事件/条件发生。这里的事件或条件是,

数据加载成功。

一旦线程 1 接收到该事件,它就会对数据执行一些处理。

线程 2,当线程 1 忙于做握手机制时并行加载数据。

当线程 2 成功地从 XML 加载数据时,它然后通过向该事件发出信号通知线程 1。

现在,当事件或条件发出信号时,线程 1 将继续处理数据。

使它成为多线程有什么好处?

当线程 1 忙于某种握手机制时,线程 2 将从 XML 并行加载数据。因此,它将提高应用程序的性能。

实现方式:

实现方式

第一种
创建一个默认为false的boolean型全局变量,在线程2中将其设为true,线程1将会循环检测其值,一旦该值被设为true,线程1将会继续处理数据,
由于它是一个由两个线程共享的全局变量,需要使用mutex锁进行同步

#include<iostream>
#include<thread>
#include<mutex>
class Application
{
 std::mutex m_mutex;
 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;
 }
 void mainTask()
 {
 std::cout<<"Do Some Handshaking"<<std::endl;
 // Acquire the Lock
 m_mutex.lock();
 // Check if flag is set to true or not
 while(m_bDataLoaded != true)
 {
  // Release the lock
  m_mutex.unlock();
  //sleep for 100 milli seconds
  std::this_thread::sleep_for(std::chrono::milliseconds(100));
  // Acquire the lock
  m_mutex.lock();
  }
  // Release the lock
  m_mutex.unlock();
  //Doc processing on loaded Data
  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;
}

 

 

该方法存在以下缺陷:
为了检测变量,线程将会持续获取-释放锁,这样会消耗CPU周期并且使线程1变慢,因为它需要获取相同的锁来更新bool变量。
因此,显然我们需要一个更好的实现机制,如某种方式,线程1可以通过等待event信号来阻塞,另一个线程可以通知该event并使线程1继续。这将会有相同的CPU周期,并有更好的性能。

第二种
我们可以使用条件变量来实现,条件变量是一种用于在2个线程之间进行信令的事件,一个线程可以等待它得到信号,其他的线程可以给它发信号。
下一节会详细说明这个条件变量,并使用条件变量来解决问题。

posted @ 2021-11-08 18:47  冰糖葫芦很乖  阅读(65)  评论(0编辑  收藏  举报