1, std::condition_variable is a conditional variable.
2, wait()
When STD:: condition_ When a wait function of the variable object is called, it uses STD:: unique_ Lock (through std::mutex) to lock the current thread. The current thread will be blocked until another thread is in the same STD:: condition_ The variable object calls the notification function to wake up the current thread.
First, let's look at a simple example 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; // Global mutex std::condition_variable cv; // Global condition variable bool ready = false; // Global flag bit void do_print_id(int id) { std::unique_lock <std::mutex> lck(mtx); while (!ready) // If the flag bit is not true, wait cv.wait(lck); // The current thread is blocked. When the global flag bit becomes true, // The thread is awakened and continues to print the thread id std::cout << "thread " << id << '\n'; } void go() { std::unique_lock <std::mutex> lck(mtx); ready = true; // Set the global flag bit to true cv.notify_all(); // Wake up all threads } 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; }
The results are as follows:
10 threads ready to race... thread 1 thread 0 thread 2 thread 3 thread 4 thread 5 thread 6 thread 7 thread 8 thread 9
std::condition_ Introduction to variable:: wait()
unconditional (1) | void wait (unique_lock<mutex>& lck); |
---|---|
predicate (2) |
|
After the current thread calls wait(), it will be blocked (at this time, the current thread should have obtained the lock (mutex), and you may wish to set the lock lck) until another thread calls notify_* Wakes up the current thread.
This function is called automatically when the thread is blocked lck.unlock() releases the lock so that other threads blocked on lock contention can continue to execute. In addition, once the current thread is notified (usually another thread calls notify_ * to wake up the current thread), the wait() function also automatically calls lck.lock(), making the lck state the same as when the wait function is called.
In the second case (that is, predict is set), the current thread will be blocked only when the pred condition is false, and the blocking will be unblocked only when PRED is true after receiving the notification from other threads.
Therefore, the second case is similar to the following code:
while (!pred()) wait(lck);
Look at the following example( reference resources):
#include <iostream> // std::cout #include <thread> // std::thread, std::this_thread::yield #include <mutex> // std::mutex, std::unique_lock #include <condition_variable> // std::condition_variable std::mutex mtx; std::condition_variable cv; int cargo = 0; bool shipment_available() { return cargo != 0; } // Consumer thread void consume(int n) { for (int i = 0; i < n; ++i) { std::unique_lock <std::mutex> lck(mtx); cv.wait(lck, shipment_available); std::cout << cargo << '\n'; cargo = 0; } } int main() { std::thread consumer_thread(consume, 10); // Consumer thread // The main thread is the producer thread, producing 10 items for (int i = 0; i < 10; ++i) { while (shipment_available()) std::this_thread::yield(); std::unique_lock <std::mutex> lck(mtx); cargo = i + 1; cv.notify_one(); } consumer_thread.join(); return 0; }
The program execution results are as follows:
concurrency ) ./ConditionVariable-wait 1 2 3 4 5 6 7 8 9 10
3, wait_for()
std::condition_variable::wait_for() introduction
unconditional (1) |
|
---|---|
predicate (2) |
|
And std::condition_variable::wait() Similarly, however, wait_for can specify a time period. The thread will be blocked before the current thread receives the notification or the specified rel_time timeout. Once the timeout or the notification from other threads is received, wait_for returns, and the remaining processing steps are similar to wait().
In addition, the last parameter PRED of the overloaded version of wait_for (predict (2)) indicates the prediction condition of wait_for. Only when the pred condition is false, the current thread will be blocked by calling wait(), and only when PRED is true after receiving the notification from other threads will it be unblocked. Therefore, it is equivalent to the following code:
return wait_until (lck, chrono::steady_clock::now() + rel_time, std::move(pred));
Look at the example below( reference resources ), in the following example, the main thread waits for the th thread to enter a value, and then prints the value received by the th thread from the terminal. Before the th thread receives the value, the main thread waits, times out every second, and prints a "."
#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(); } 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) { std::cout << '.'; std::cout.flush(); } std::cout << "You entered: " << value << '\n'; th.join(); return 0; }