condition_variable
这是一个等待条件成立,然后唤醒线程的机制
wait() 等待被唤醒
notify_one()唤醒一个卡在wait处的线程
notify_all()唤醒所有卡在wait处的线程
有些线程的执行有条件限制,例如:只有在队列中有元素的情况下才执行弹出和删除元素的操作。
用法是先声明一个condition_variable 的变量conv
在线程中使用 conv.wait( para1, para2 )
第一个参数是一个unique_guard对象
第二个参数是一个可调用对象(可以是一个lambda表达式),如下所示
unique_lock<mutex> guard(m_Mutex); //先锁住
conv.wait( guard, [this] {return !m_Queue.empty();} );
如果参数二返回的是true,程序继续运行。
如果是false,则解锁,然后卡住,指导被唤醒,再次锁住互斥量,重新进行判断
这个过程可以理解为:
下面是一个对C++11多线程(二)中的代码的改进
class A
{
deque<int> m_Queue;
mutex m_Mutex;
std::condition_variable conv;
public:
unique_lock<mutex> rtn_lock()
{
unique_lock<mutex> temp(m_Mutex);
return temp;//返回局部对象,调用移动构造函数
}
void inMessage()
{
for (int i = 0; i < 100000; i++)
{
cout << "in " << i << endl;
unique_lock<mutex> guard = rtn_lock();
m_Queue.push_back(i);
conv.notify_one();//插入元素后就唤醒线程outMessage继续执行
}
}
void outMessage()
{
for (int i = 0; i < 100000; i++)
{
int command = -1;
while (true)
{
unique_lock<mutex> guard1(m_Mutex);
conv.wait(guard1, [this] {
if (!m_Queue.empty())return true;//如果非空,就可以对m_Queue进行接下来的操作
return false;//如果为空,就解锁,然后等着,直到被notify_one唤醒,再次锁住互斥量,重新判断
});
command = m_Queue.front();
m_Queue.pop_front();
guard1.unlock();
cout << "out " << command << endl;
}
}
}
};
int main()
{
A a;
thread tobjin(&A::inMessage, std::ref(a));
thread tobjout(&A::outMessage, std::ref(a));
tobjin.join();
tobjout.join();
system("pause");
return 0;
}
注意:只有当一个线程卡在wait()的时候,另一个线程的notify_one才有效
唤醒之后并不一定就会马上执行,应为唤醒之后还要加锁,并不一定能成功加锁,可能被另一个线程先锁了。