c++多线程基础4(条件变量)

条件变量是允许多个线程相互交流的同步原语。它允许一定量的线程等待(可以定时)另一线程的提醒,然后再继续。条件变量始终关联到一个互斥

定义于头文件 <condition_variable>

condition_variable:

condition_variable 类是同步原语,能用于阻塞一个线程,或同时阻塞多个线程,直至另一线程修改共享变量(条件)并通知 condition_variable 。

有意修改变量的线程必须

  1. 获得 std::mutex (典型地通过 std::lock_guard )
  2. 在保有锁时进行修改
  3. 在 std::condition_variable 上执行 notify_one 或 notify_all (不需要为通知保有锁)

即使共享变量是原子的,也必须在互斥下修改它,以正确地发布修改到等待的线程。

任何有意在 std::condition_variable 上等待的线程必须

  1. 获得 std::unique_lock<std::mutex> ,在与用于保护共享变量者相同的互斥上
  2. 执行 wait 、 wait_for 或 wait_until ,等待操作自动释放互斥,并悬挂线程的执行
  3. condition_variable 被通知时,时限消失或虚假唤醒发生,线程被唤醒,且自动重获得互斥。之后线程应检查条件,若唤醒是虚假的,则继续等待

代码:

 1 #include <iostream>
 2 #include <thread>
 3 #include <mutex>
 4 #include <condition_variable>
 5 using namespace std;
 6 
 7 std::mutex m;
 8 std::condition_variable cv;
 9 string data;
10 bool ready = false;
11 bool processed = false;
12 
13 void worker_thread() {
14     //等待直至 main() 发送数据
15     std::unique_lock<std::mutex> lk(m);//拥有mutex,并调用mutex.lock()对其上锁
16     cv.wait(lk, []{return ready;});//等价于 while(!ready) cv.wait(lk);
17     //在调用 wait 时会自动执行 lk.unlock()
18     //当 wait 被其它线程唤醒时,锁会自动恢复 wait 之前的状态
19 
20     //等待后,我们占有锁
21     cout << "worker thread is processing data
";
22     data += " after processing";
23 
24     //发送数据回 main
25     processed = true;
26     cout << "worker thread sigals data processing completed
";
27 
28     lk.unlock();//通知前手动解锁,以避免等待线程再阻塞
29     cv.notify_one();
30 }
31 
32 int main(void) {
33     std::thread worker(worker_thread);
34 
35     data = "Example data";
36     //发送数据到worker线程
37     {
38         std::lock_guard<std::mutex> lk(m);
39         ready = true;
40         cout << "main() sigals data ready for processing
";
41     }
42     cv.notify_one();
43 
44     //等候worker
45     {
46         std::unique_lock<std::mutex> lk(m);
47         cv.wait(lk, []{return processed;});//等价于while(!processed) cv.wait(lk)
48     }
49     cout << "Back in main(), data = " << data << '
';
50 
51     worker.join();
52 
53 // 输出:
54 // main() sigals data ready for processing
55 // worker thread is processing data
56 // worker thread sigals data processing completed
57 // Back in main(), data = Example data after processing
58 
59     return 0;
60 }
View Code

注意:虚假唤醒问题 https://segmentfault.com/q/1010000010421523/a-1020000010457503

https://blog.csdn.net/shizheng163/article/details/83661861

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

原文地址:https://www.cnblogs.com/geloutingyu/p/8544543.html