- 调用wait函数时,即使没有notify,也会执行一次检查。
- notify和wait苏醒执行检查的次数不一定相等。
- 条件检查在第一次之后,只能由notify触发。改变条件不调用notify,永远不会主动执行检查,即永远阻塞。执行检查时才会持有锁,不执行检查时不会持有锁。
- 条件变量的wait和notify本身是不需要锁保护的
1.调用wait函数时,即使没有notify,也会执行一次检查。
如下,只调用wait,也会打印出m_num的值。
class CV
{
public:
void Notify()
{
m_mutex.lock();
m_num++;
m_mutex.unlock();
m_cv.notify_all();
}
void Wait()
{
std::unique_lock<std::mutex> guard(m_mutex);
m_cv.wait(guard, [this]() {
cout << m_num << endl;
return false;
});
}
public:
std::condition_variable m_cv;
std::mutex m_mutex;
int m_num = 0;
};
int main()
{
CV cv;
cv.Wait();
return 0;
}
2.notify和wait苏醒执行检查的次数不一定相等。
下面的代码,notify了2次,但只唤醒了1次。
int main()
{
CV cv;
std::thread t([&cv]() {
std::this_thread::sleep_for(chrono::milliseconds(100));
while (true)
{
cv.Wait();
}
});
cv.Notify();
cv.Notify();
while (true)
{
std::this_thread::sleep_for(chrono::milliseconds(100));
}
return 0;
}
3.条件检查在第一次之后,只能由notify触发。改变条件不调用notify,永远不会主动执行检查,即永远阻塞。
下面的代码,子线程永远不会退出,即使主线程将m_num的值设为大于0.
class CV
{
public:
void Notify()
{
m_mutex.lock();
m_num++;
m_mutex.unlock();
m_cv.notify_all();
}
void Wait()
{
std::unique_lock<std::mutex> guard(m_mutex);
m_cv.wait(guard, [this]() {
cout << m_num << endl;
return m_num > 0;
});
}
public:
std::condition_variable m_cv;
std::mutex m_mutex;
int m_num = 0;
};
int main()
{
CV cv;
std::thread t([&cv]() {
cv.Wait();
cout << "sub thread return " << endl;
});
std::this_thread::sleep_for(chrono::milliseconds(100));
cv.m_num++;
while (true)
{
std::this_thread::sleep_for(chrono::milliseconds(100));
}
return 0;
}
4.notify_all()本身是线程安全的,不需要锁保护。但放到锁内也是可以的。
void Notify()
{
m_mutex.lock();
m_num++;
m_mutex.unlock();
m_cv.notify_all();
}
void Notify()
{
m_mutex.lock();
m_num++;
m_cv.notify_all();
m_mutex.unlock();
}