c++11 std::condition_variable

发布时间 2023-08-02 22:15:09作者: BuzzWeek

std::condition_variable

  • 需要配合unique_lock使用,wait(unique_lock<mutex>&)
  • notify_one()调用时,只有随机一个wait()线程会得到通知
  • notify_all(),所有wait()线程会被通知并得到执行
  • wait()调用会阻塞当前线程
  • wait()线程中用到的unique_lock不会阻塞notify线程中的锁
// condition_variable example
#include <iostream>           // std::cout
#include <thread>             // std::thread
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
#include <chrono>

using namespace std;

namespace {
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
}

void print_id (int id) {
  std::unique_lock<std::mutex> lck(mtx);              // 这里必须使用unique_lock
  while (!ready) {
    cv.wait(lck);                                     // 这里会阻塞
    cout << "thead " << id << " notifyed..." << endl; // 被notify后才能执行
  }
  std::cout << "thread " << id << '\n';
}

void go() {
  this_thread::sleep_for(1s);             // 观察是否会被抢占mutex而阻塞(不会!)
  // std::unique_lock<std::mutex> lck(mtx);  
  std::lock_guard<std::mutex> lck(mtx);   // 这里unique_lock或者lock_gurad都行
  ready = true;
  this_thread::sleep_for(2s);
  // cv.notify_one(); // 只有一个cv.wait(lck)线程会被notify,这里因为所有10个线程都在join,会导致死锁
  cv.notify_all();    // 所有cv.wait(lck)线程会被notify
}

void ConditionVariableTest()
{
  std::thread threads[10];
  // spawn 10 threads:
  for (int i=0; i<10; ++i)
    threads[i] = std::thread(print_id,i);

  std::cout << "10 threads ready to race...\n";
  go();                       // go!

  for (auto& th : threads) th.join();
}