多线程之条件变量

11 篇文章 0 订阅

在C++11可以使用条件变量(condition_variable)实现多个线程间的同步操作;当条件不满足时,相关线程被一直阻塞,直到某种条件出现,这些线程才会被唤醒。
c++ 参考手册网站:http://www.cppds.com/
主要成员函数:

 1、wait函数:
(1)wait(unique_lock <mutex>&lck)   没有第二个参数收到notify时直接返回不阻塞

当前线程的执行会被阻塞,直到收到 notify 为止。

(2)wait(unique_lock <mutex>&lck,Predicate pred)

当前线程仅在pred=false时解锁然后阻塞,直至收到notify_one();如果pred=true时,不阻塞  直接返回。

wait()可依次拆分为三个操作:释放互斥锁、等待在条件变量上、再次获取互斥锁

wait_for()函数
 while (cv.wait_for(lck,std::chrono::seconds(1)) == std::cv_status::timeout) { //这里wait_for堵塞到这一行,解锁互斥量。
               std::cout << '.';                                                //这里wait_for堵塞到这一行,解锁互斥量。
               std::cout << '.';                                                  //当超时1s的时候,相当于收到了通知信号,就被唤醒干活了。 加锁互斥量
               std::cout.flush();                                                 //while语句满足就执行打印.
    }                                                                             //然后再次循环再wait等待1s,循环反复。
                                                                                  //但是当收到cv.notify_one();的时候,不满足 std::cv_status::timeout,就会退出循环。
       

2、notify_one:
notify_one():没有参数、没有返回值。 唤醒wait()的线程,不断 尝试获取互斥量锁获取不到就阻塞到wait(), 获取到锁(加锁)就继续往下执行


解除阻塞当前正在等待此条件的线程之一。如果没有线程在等待,则还函数不执行任何操作。如果超过一个,不会指定具体哪一线程。


// condition_variable::notify_one
#include <iostream>           // std::cout
#include <thread>             // std::thread
#include <mutex>              // std::mutex, std::unique_lock    //可随时调用unlock() 提前解锁
#include <condition_variable> // std::condition_variable

std::mutex mtx;
std::condition_variable produce,consume;

int car = 0;     // 共享资源

void consumer () {
  std::unique_lock<std::mutex> lck(mtx);
  while (car ==0) consume.wait(lck);   
  std::cout << car << '\n';       //执行到此说明已经上锁
  car =0;
  produce.notify_one();
}

void producer (int id) {
  std::unique_lock<std::mutex> lck(mtx);
  while (car !=0) produce.wait(lck);
  car = id;     
  consume.notify_one();
}

int main ()
{
  std::thread consumers[10],producers[10];
  for (int i=0; i<10; ++i) {
    consumers[i] = std::thread(consumer);
    producers[i] = std::thread(producer,i+1);
  }

  // join them back:
  for (int i=0; i<10; ++i) {
    producers[i].join();
    consumers[i].join();
  }

  return 0;
}
分析
条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:

(1)、一个线程因等待“条件变量的条件成立”而挂起;

(2)、另外一个线程使“条件成立”,给出信号,从而唤醒被等待的线程。


想要修改共享变量(即“条件”)的线程必须:
(1). 获得一个std::mutex
(2). 当持有锁的时候,执行修改动作
(3). 对std::condition_variable执行notify_one或notify_all(当做notify动作时,不必持有锁)

即使共享变量是原子性的,它也必须在mutex的保护下被修改,这是为了能够将改动正确发布到正在等待的线程。

任意要等待std::condition_variable的线程必须:
(1). 获取std::unique_lock<std::mutex>,这个mutex正是用来保护共享变量(即“条件”)的
(2). 执行wait, wait_for或者wait_until. 这些等待动作原子性地释放mutex,并使得线程的执行暂停
(3). 当获得条件变量的通知,或者超时,或者一个虚假的唤醒,那么线程就会被唤醒,并且获得mutex. 然后线程应该检查条件是否成立,如果是虚假唤醒,就继续等待。

虚假唤醒,就是因为某种未知的罕见的原因,线程被从等待状态唤醒了,但其实共享变量(即条件)并未变为true。因此此时应继续等待

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值