(192条消息) 《c++新经典》C++11并发与多线程笔记(8)_中国彭于晏杭州分晏的博客-CSDN博客
问题一:如果说第一个读数据的线程中, wait第二个参数返回的是false的话,程序就会阻塞,沉睡在这里,直到另一个线程使用notify_one函数为止,notice_one函数将其唤醒后,wait就开始工作了。
恢复wait()后干什么活?
1.wait()会和其他的线程继续竞争锁,不断尝试重新获取互斥量锁,如果获取不到,那么流程就卡在wait这里等着获取;
如果获取到了(等于加了锁),那么wait就继续执行
如果wait有第二个参数(lambda表达式),就判断这个lambda表达式,
如果lambda表达式为false,那wait又对互斥量解锁,然后又休眠等待再次被唤醒
如果lambda表达式为true,则wait返回,流程走下来(此时,互斥锁被锁着)
如果wait没有第2个参数,则wait返回,流程走下来。
值得注意的是notify_one只有在wait()沉睡的时候才会有唤醒的功能。
问题二:为什么需要wait()?
//把消息队列从容器中取出来的线程
void outMesgRecvQueue()
{
for (int i = 0; i < 100000; ++i)
{ std::lock(my_mutex1, my_mutex2);//std::lock(my_mutex);
if (!list_msg.empty())
{
int command = list_msg.front();
list_msg.pop_front();
my_mutex.unlock();
}
else
{
cout << "消息队列为空" << endl;
}
}
cout << "outMesgRecvQueue end" << endl;
}
其实是为了节约资源,因为,我们在取数据的时候,需要现有个判空函数,判空其实和读数据的线程就有冲突了,所以要在判空之前加上锁,但是每一次判空前都要加锁的话,就会浪费资源,为此,我们可以用双重检测的写法。
void outMesgRecvQueue()
{
for (int i = 0; i < 100000; ++i)
{ if(!list_msg.empty()){
std::lock(my_mutex1, my_mutex2);//std::lock(my_mutex);
if (!list_msg.empty())
{
int command = list_msg.front();
list_msg.pop_front();
my_mutex.unlock();
}
}
else
{
cout << "消息队列为空" << endl;
}
}
cout << "outMesgRecvQueue end" << endl;
}
但是这样的写法,思路比较难受为此我们使用了条件变量。引用了wait(锁,条件判断的lambada函数),当判断函数(其实就是判空函数,返回了true)则线程就可以继续走下去,否则就等待别的线程中的notify_one唤醒。