一、条件变量 condition_variable wait notify_one
1.condition_variable
- condition_variable :实际上是一个类,等待一个条件达成,需要和互斥量来配合,用的时候我们要生成这个类的对象
2.wait()函数
条件变量类对象的成员函数,用来等一个东西 ;
- 如果第二个参数的lambda表达式返回 true , 那么wait()最接返回;
- 如果第二个参数的lambda表达式返回 false ,那么wait()将解锁互斥量,并阻塞到本行;阻塞到其他某个线程调用notify_one()成员函数为止;
- 如果wait()没有第二个参数 varible.wait(unique) ;那么就和第二个参数lambda表达式返回false效果一样;
- 当其他线程用notify_one()将本wait(原来是阻塞)的状态唤醒后,wait()会不断的尝试重新获取互斥量锁 ;如果获取不到,那么就会卡在wait()这里等着,如果获取到了,wait()就继续执行上锁;
- 如果wait()有第二个参数lambda表达式,如果表达式为false 那么wait()将解锁互斥量,并阻塞到本行;如果为 true 则返回,流程就继续走下去(此时互斥锁被锁着);
- 如果wait没有第二个参数 ,则wait()返回,流程将继续走下去
while (true)
{
unique_lock<std::mutex> unique(mutex1);
//wait() 条件变量类对象的成员函数,用来等一个东西
//如果第二个参数的lambda表达式返回 true , 那么wait()最接返回
//如果第二个参数的lambda表达式返回 false ,那么wait()将解锁互斥量,并阻塞到本行
//阻塞到其他某个线程调用notify_one()成员函数为止
//如果wait()没有第二个参数 varible.wait(unique) ;那么就和第二个参数lambda表达式返回false效果一样
//当其他线程用notify_one()将本wait(原来是阻塞)的状态唤醒后,wait()会不断的尝试重新获取互斥量锁
//如果获取不到,那么就会卡在wait()这里等着,如果获取到了,wait()就继续执行上锁,如果wait()有第二个参数lambda表达式,如果表达式为
// false 那么wait()将解锁互斥量,并阻塞到本行
// 如果为 true 则返回,流程就继续走下去(此时互斥锁被锁着)
// 如果wait没有第二个参数 ,则wait()返回,流程将继续走下去
varible.wait(unique, [this]() { //一个lambda就是一个可调用对象
if (!m_list.empty())
{
return true;
}
return false;
});
nCommand = m_list.front(); //返回第一个元素,但不检查元素是否存在 所以要判断是否为空
m_list.pop_front(); //移除第一个元素,但不返回
unique.unlock(); //因为unique_lock的灵活性,我们可以随时unlock解锁,以免锁太长时间
cout << "移除一个元素 : " << nCommand << endl;
}
完整代码演示:
class Test
{
public:
Test() {};
~Test() {};
//把收到的消息(玩家命令)入到一个队列的线程
void InQueue()
{
for (int i = 0; i < 100000; ++i)
{
cout << "插入一个元素 : " << i << endl;
std::lock_guard<std::mutex> guard1(mutex1);
m_list.push_back(i);
varible.notify_one(); //我们尝试把wait()的线程唤醒 执行完这行 那么OutQueue()里面的wait()就会被唤醒
}
}
//出队列线程函数
void OutQueue()
{
int nCommand = 0;
while (true)
{
unique_lock<std::mutex> unique(mutex1);
varible.wait(unique, [this]() { //一个lambda就是一个可调用对象
if (!m_list.empty())
{
return true;
}
return false;
});
nCommand = m_list.front(); //返回第一个元素,但不检查元素是否存在 所以要判断是否为空
m_list.pop_front(); //移除第一个元素,但不返回
unique.unlock(); //因为unique_lock的灵活性,我们可以随时unlock解锁,以免锁太长时间
cout << "移除一个元素 : " << nCommand << endl;
}
}
private:
list<int> m_list; //容器(消息队列),专门用于代表玩家发过来的命令
mutex mutex1;
condition_variable varible; //条件变量对象
};
int main()
{
Test test;
thread obj1(&Test::InQueue, &test);
thread obj2(&Test::OutQueue, &test);
obj1.join();
obj2.join();
cout << "I Love China" << endl;
return 0;
}