admin管理员组

文章数量:1599528

目录

1、std::condition_variable

2、std::condition_variable::notify_all、std::condition_variable::notify_one

3、std::condition_variable::wait、std::condition_variable::wait_for、std::condition_variable::wait_until

4、condition_variable_any


1、std::condition_variable

A condition variable is an object able to block the calling thread until notified to resume.

It uses a unique_lock (over a mutex) to lock the thread when one of its wait functions is called. The thread remains blocked until woken up by another thread that calls a notification function on the same condition_variable object.

Objects of type condition_variable always use unique_lock<mutex> to wait: for an alternative that works with any kind of lockable type, see condition_variable_any

example:

#include <iostream>           // std::cout
#include <thread>             // std::thread
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void print_id (int id) {
  std::unique_lock<std::mutex> lck(mtx);
  while (!ready) cv.wait(lck);
  std::cout << "thread " << id << '\n';
}

void go() {
  std::unique_lock<std::mutex> lck(mtx);
  ready = true;
  std::cout << ready << '\n';
  cv.notify_all();
  std::cout << "go end" << '\n';
}

int main ()
{
  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";
  std::this_thread::sleep_for (std::chrono::seconds(3));
  go();                       // go!

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

  return 0;
}

possible output:

代码中涉及了两个新的函数wait()与notify_all(),功能就是单词的表面意思(Wait until notified、notify all)。

如果去掉go()函数中的“cv.notify_all();”这一行,则执行结果如下:

很好理解,就是没有接受到通知,就一直在等待。线程进入所谓死锁状态。

那如果彻底不调用go()函数呢,会是啥结果,执行结果如下:

2、std::condition_variable::notify_all、std::condition_variable::notify_one

notify_one define:

Unblocks one of the threads currently waiting for this condition.

If no threads are waiting, the function does nothing.

If more than one, it is unspecified which of the threads is selected.

example(producer and consumer):

#include <iostream>           // std::cout
#include <thread>             // std::thread
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

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

int cargo = 0;     // shared value by producers and consumers

void consumer () {
  std::unique_lock<std::mutex> lck(mtx);
  while (cargo==0) consume.wait(lck);
  std::cout << cargo << '\n';
  cargo=0;
  produce.notify_one();
}

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

int main ()
{
  std::thread consumers[10],producers[10];
  // spawn 10 consumers and 10 producers:
  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;
}

possible output:

但是如果第一个例子中10个线程我们采用的是notify_all(),如果使用notify_one()。看一下所谓的“unspecified which of the threads is selected”究竟是咋回事

运行结果:

结果是一个都没唤醒。

3、std::condition_variable::wait、std::condition_variable::wait_for、std::condition_variable::wait_until

std::condition_variable::wait define:

The execution of the current thread (which shall have locked lck's mutex) is blocked until notified.

At the moment of blocking the thread, the function automatically calls lck.unlock(), allowing other locked threads to continue.

Once notified (explicitly, by some other thread), the function unblocks and calls lck.lock(), leaving lck in the same state as when the function was called. Then the function returns (notice that this last mutex locking may block again the thread before returning).

std::condition_variable::wait_for define:

Wait for timeout or until notified
The execution of the current thread (which shall have locked lck's mutex) is blocked during rel_time, or until notified (if the latter happens first).

At the moment of blocking the thread, the function automatically calls lck.unlock(), allowing other locked threads to continue.

Once notified or once rel_time has passed, the function unblocks and calls lck.lock(), leaving lck in the same state as when the function was called. Then the function returns (notice that this last mutex locking may block again the thread before returning).

std::condition_variable::wait_until define:

Wait until notified or time point
The execution of the current thread (which shall have locked lck's mutex) is blocked either until notified or until abs_time, whichever happens first.

At the moment of blocking the thread, the function automatically calls lck.unlock(), allowing other locked threads to continue.

Once notified or once it is abs_time, the function unblocks and calls lck.lock(), leaving lck in the same state as when the function was called. Then the function returns (notice that this last mutex locking may block again the thread before returning).

4、condition_variable_any

condition_variable_any 类是 std::condition_variable 的泛化。相对于只在 std::unique_lock<std::mutex> 上工作的 std::condition_variable , condition_variable_any 能在任何满足基本可锁定 (BasicLockable) 要求的锁上工作。

条件变量语义描述见 std::condition_variable 。

类 std::condition_variable_any 是标准布局类型 (StandardLayoutType) 。它非可复制构造 (CopyConstructible) 、可移动构造 (MoveConstructible) 、可复制赋值 (CopyAssignable) 或可移动赋值 (MoveAssignable) 。

若锁是 std::unique_lock ,则 std::condition_variable 可能提供更好的性能。

本文标签: conditionvariableconditionvariableanystdnotifyallwaitfor