并发编程(4)同步并发操作

一、主要涉及

  1. 等待事件
  2. 带有期望的等待一次性事件
  3. 在限定时间内等待
  4. 使用同步操作简化代码

  在上一章中,我们看到各种在线程间保护共享数据的方法。当你不仅想要保护数据,还想对单独的线程进行同步。例如,在第一个线程完成前,可能需要等待另一个线程执行完成。 C++ 标准库提供了一些工具可用于同步操作,形式上表现为条件变量(condition variables)和期望(futures)。

二、等待一个条件或者事件

     1、选择是在等待线程在检查间隙,使用 std::this_thread::sleep_for() 进行周期性的间歇;

     2、(也是优先的选择)是,使用C++标准库提供的工具去等待事件的发生。通过另一线程触发等待事件的机制是最基本的唤醒方式(例如:流水线上存在额外的任务时),这种机制就称为“条件变量”。从概念上来说,一个条件变量会与多个事件或其他条件相关,并且一个或多个线程会等待条件的达成。

    C++标准库对条件变量有两套实现: std::condition_variable 和 std::condition_variable_any

展示了一种使用条件变量做唤醒的方式:

std::mutex mut;
std::queue<data_chunk> data_queue; // 1
std::condition_variable data_cond;
//准备数据线程
void data_preparation_thread() {   while(more_data_to_prepare())   {   data_chunk const data=prepare_data();   std::lock_guard<std::mutex> lk(mut);//队列上锁   data_queue.push(data); // 2 将数据压入队列   data_cond.notify_one(); // 3std::condition_variable 的notify_one()成员函数,对等待的线程(如果有等待

                               //线程)进行通知

     }

}

//处理数据线程

void data_processing_thread()

{
while(true)
  {
  std::<std::mutex> lk(mut); //
  data_cond.wait(
      lk,[]{return !data_queue.empty();}//检测队列是否有数据写入了
          ); // 5   data_chunk data=data_queue.front();//对数据处理   data_queue.pop();   lk.unlock(); // 6   process(data);   if(is_last_chunk(data))   break;   } }

       wait()会去检查这些条件(通过调用所提供的lambda函数),当条件满足(lambda函数返回true)
时返回。如果条件不满足(lambda函数返回false),wait()函数将解锁互斥量,并且将这个线程
(上段提到的处理数据的线程)置于阻塞或等待状态。

       条件变量时,处理数据的线程从睡眠状态中苏醒,重新获取互斥锁,并且对条件再次检查,在条件满足的情况下,从wait()返回并继续持有锁当条件不满足时,线程将对互斥量解锁,并且重新开始等待。这就是为什么用 std::unique_lock (4)而不使用 std::lock_guard ——等待中的线程必须在等待期间解锁互斥量,并在这这之后对互斥量再次上锁。

三、期望

四、信号量

原文地址:https://www.cnblogs.com/huangfuyuan/p/9129340.html