std::condition_variable的成员函数notify_one()与notify_all()是用来唤醒阻塞在wait()的线程。假如有多个线程调用condition_variable::wait()陷入休眠之后。condition_variable的实现中有一个等待队列来保存堵塞在它之上的线程。当其他线程调用notify_one()时,只唤醒等待队列中的第一个线程;其余的线程不会被唤醒,需要等待再次调用notify_one()或者notify_all()才会唤醒。如果是调用notify_all():会唤醒所有等待队列中阻塞的线程,但是存在锁争用,只有一个线程能够获得锁。队列中的其他线程,会不断尝试获得锁,当第一个唤醒的线程释放锁之后,剩余的线程就能获得锁继续执行。 如下程序:
#include <iostream>
#include <condition_variable>
#include <thread>
#include <chrono>
std::condition_variable cv;
std::mutex cv_m;
int i = 0;
void waits()
{
std::unique_lock<std::mutex> lk(cv_m);
std::cerr << "Waiting... \n";
cv.wait(lk);
i++;
std::cerr << "...finished waiting. i:"<<i<<std::endl;
}
void signals()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lk(cv_m);
std::cerr << "Notifying...\n";
}
cv.notify_all();
}
int main()
{
std::thread t1(waits), t2(waits), t3(waits), t4(signals);
t1.join();
t2.join();
t3.join();
t4.join();
}
输出:
Waiting… Waiting… Waiting… Notifying… …finished waiting. i:1 …finished waiting. i:2 …finished waiting. i:3
main只调用一次notify_all()便激活了三个线程,这个三个线程依次执行。再来看一下notify_one()的情况
#include <iostream>
#include <condition_variable>
#include <thread>
#include <chrono>
std::condition_variable cv;
std::mutex cv_m;
int i = 0;
void waits()
{
std::unique_lock<std::mutex> lk(cv_m);
std::cerr << "Waiting... \n";
cv.wait(lk);
i++;
std::cerr << "...finished waiting. i:"<<i<<std::endl;
}
void signals()
{
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lk(cv_m);
std::cerr << "Notifying...\n";
}
cv.notify_one();
}
int main()
{
std::thread t1(waits), t2(waits), t3(waits), t4(signals);
t1.join();
t2.join();
t3.join();
t4.join();
}
代码值改动了一个地方,输出为:
Waiting… Waiting… Waiting… Notifying… …finished waiting. i:1 execution expired
只有一个线程被激活
|