std::condition_variable 是与 std::mutex 一起使用的同步原语,它能用于阻塞一个线程,或同时阻塞多个线程,直至另一线程修改共享变量(条件)并通知 std::condition_variable。
有意修改共享变量的线程必须
1.获得 std::mutex(常通过 std::lock_guard)
2.在保有锁时进行修改
3.在std::condition_variable上执行notify_one或notify_all(可以释放锁后再通知)
即使共享变量是原子的,也必须在拥有互斥体时修改它,以把修改发布到等待的线程。
下面来看具体的使用示例
//condition_variable.cpp condition_variable example //#include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex #include <condition_variable> #include <string> std::mutex mtx; std::condition_variable cv; std::string data; bool ready = false; bool processed = false; void worker_thread() { //等待直至 main() 发送数据 std::unique_lock lk(mtx); printf("worker_thread=1============ready=======%d\n", ready); cv.wait(lk, [] {return ready; }); printf("worker_thread=2============ready=======%d\n", ready); std::this_thread::sleep_for(std::chrono::seconds(2)); //暂停2秒 // 等待后,我们占有锁 printf("工作线程正在处理数据\n"); data += "(处理后)"; // 发送数据回 main() processed = true; printf("工作线程指示数据已经处理完成\n"); // 通知前完成手动解锁,以避免等待线程才被唤醒就阻塞(细节见 notify_one) lk.unlock(); cv.notify_one(); } int main() { //1.记录开始时间点 auto start = std::chrono::steady_clock::now(); std::thread worker(worker_thread); data = "数据样例"; // 发送数据到 worker 线程 { std::lock_guard lk(mtx); //std::this_thread::sleep_for(std::chrono::seconds(2)); //暂停2秒 ready = true; printf("main() 指示数据已准备好进行处理\n"); } cv.notify_one(); // 等候 worker { std::unique_lock lk(mtx); printf("main=1============processed=======%d\n", processed); cv.wait(lk, [] { return processed; }); printf("main=2============processed=======%d\n", processed); } printf("返回 main(),data = %s\n", data.c_str()); worker.join(); //2.记录结束时间点 auto end = std::chrono::steady_clock::now(); //3.计算时间差 auto elapsed = end - start; printf("耗时: %lld 纳秒\n", std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed).count()); printf("耗时: %lld 微秒\n", std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count()); printf("耗时: %lld 毫秒\n", std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count()); printf("耗时: %lld 秒\n", std::chrono::duration_cast<std::chrono::seconds>(elapsed).count()); printf("hello learn condition_variable\n"); return 0; }编译运行:
下面来看wait()一个参数的示例
//condition_variable2.cpp condition_variable example //#include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex #include <condition_variable> std::mutex mtx; std::condition_variable cv; bool ready = false; void print_id(int id) { std::unique_lock<std::mutex> lck(mtx); printf("print_id=1============id=======%d\n", id); while (!ready) cv.wait(lck); printf("print_id=2============id=======%d\n", id); std::this_thread::sleep_for(std::chrono::seconds(1)); //暂停2秒 printf("thread========id=%d\n", id); } void go() { std::unique_lock<std::mutex> lck(mtx); printf("go=1====================\n"); //std::this_thread::sleep_for(std::chrono::seconds(12)); //暂停2秒 ready = true; cv.notify_all(); //通知所有线程 } int main() { //1.记录开始时间点 auto start = std::chrono::steady_clock::now(); std::thread threads[10]; // spawn 10 threads: for (int i = 0; i < 10; ++i) threads[i] = std::thread(print_id, i); printf("10 threads ready to race...\n"); go(); printf("main=1====================\n"); for (auto& th : threads) th.join(); printf("main=1====================\n"); //2.记录结束时间点 auto end = std::chrono::steady_clock::now(); //3.计算时间差 auto elapsed = end - start; printf("耗时: %lld 纳秒\n", std::chrono::duration_cast<std::chrono::nanoseconds>(elapsed).count()); printf("耗时: %lld 微秒\n", std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count()); printf("耗时: %lld 毫秒\n", std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count()); printf("耗时: %lld 秒\n", std::chrono::duration_cast<std::chrono::seconds>(elapsed).count()); printf("hello learn condition_variable\n"); return 0; }编译运行:
参考:
https://zh.cppreference.com/cpp/thread/condition_variable
https://cplusplus.com/reference/condition_variable/condition_variable/
https://blog.csdn.net/m0_67168421/article/details/128302838
https://blog.csdn.net/FL1768317420/article/details/136613939
https://blog.csdn.net/u011808673/article/details/91783965
https://liucjy.blog.csdn.net/article/details/130298493
https://lizuohao.blog.csdn.net/article/details/136274149