介绍condition_variable, wait,wait_for
直接上代码如下:
#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 do_print_id(int id) { std::unique_lock <std::mutex> lck(mtx); // 加锁互斥量 while (!ready) { cv.wait(lck); // 当ready==false的时候,while语句执行到wait这里,然后就堵塞到这行,等到通知信号,同时解锁互斥量,不影响其他线程获取锁。 } //当 cv.notify_all(); // 唤醒所有线程. 执行到这句wait就收到了信号就被唤醒开始干活,首先就是不断的尝试重新获取并加锁互斥量。 //若获取不到锁就卡在这里反复尝试加锁 //若获取到了锁才往下执行 std::cout << "thread " << id << '\n'; } void go() { std::unique_lock <std::mutex> lck(mtx); ready = true; // 设置全局标志位为 true. cv.notify_all(); // 唤醒所有线程. } int main() { std::thread threads[10]; // spawn 10 threads: for (int i = 0; i < 10; ++i) threads[i] = std::thread(do_print_id, i); std::cout << "10 threads ready to race...\n"; go(); // go! for (auto & th:threads) th.join(); return 0; }
与std::condition_variable::wait() 类似,不过 wait_for可以指定一个时间段,在当前线程收到通知或者指定的时间 rel_time 超时之前,该线程都会处于阻塞状态。
而一旦超时或者收到了其他线程的通知,wait_for返回,剩下的处理步骤和 wait()类似。
#include <iostream> // std::cout #include <thread> // std::thread #include <chrono> // std::chrono::seconds #include <mutex> // std::mutex, std::unique_lock #include <condition_variable> // std::condition_variable, std::cv_status std::condition_variable cv; int value; void do_read_value() { std::cin >> value; cv.notify_one(); //只有键盘敲入一个字符,才往下执行cv.notify_one(); } int main () { std::cout << "Please, enter an integer (I'll be printing dots): \n"; std::thread th(do_read_value); std::mutex mtx; std::unique_lock<std::mutex> lck(mtx); //加锁互斥量 while (cv.wait_for(lck,std::chrono::seconds(1)) == std::cv_status::timeout) { //这里wait_for堵塞到这一行,解锁互斥量。 std::cout << '.'; //当超时1s的时候,相当于收到了通知信号,就被唤醒干活了。 加锁互斥量 std::cout.flush(); //while语句满足就执行打印. } //然后再次循环再wait等待1s,循环反复。 //但是当收到cv.notify_one();的时候,不满足 std::cv_status::timeout,就会退出循环。 std::cout << "You entered: " << value << '\n'; //这个时候不断尝试加锁互斥量,加锁成功往下执行。加锁不成功不断尝试加锁。 th.join(); return 0; }
这里的现像就是终端不断的在打印.
Please, enter an integer (I'll be printing dots): .................................
当我敲一个字符的时候,就会停止打印
Please, enter an integer (I'll be printing dots): ...............................................................................q. You entered: 0 按 <RETURN> 来关闭窗口...