條件變量condition_variable
假設有兩個線程,一個線程A一個線程B。
線程A:等待一個條件滿足.
線程B:專門往消息隊列中扔消息(數據)
condition_variable
是一個類,和條件相關的類,等待一個條件完成,需要和互斥量配合工作,用的時候需要生成這個類的對象。
condition_variable
成員函數wait
第一個參數是一個鎖,第二個參數是一個可調用對象。
如果第二個參數返回true,wait()直接返回。
如果第二個參數返回false,那麼wati()將解鎖互斥量,並堵塞直到其他某個線程調用notify_one()成員函數爲止。
如果wait()沒有第二個參數,那麼就和第二個參數返回false的效果一樣。
wait喚醒後,wait將幹以下工作:
1.不斷嘗試重新獲取互斥量鎖,如果獲取不到,流程就卡在wait這裏等着獲取,如果獲取獲取到了就繼續執行2
2.獲取到了鎖然後上鎖,如果wait有第二個參數,就判斷第二個參數,如果第二個參數返回false,那wait又解鎖互斥量,並堵塞直到其他某個線程調用notify_one()成員函數爲止。
3.如果第二個參數返回true,則wait返回,流程走下去。
4.如果沒有第二個參數,wait返回,流程走下去。
condition_variable
成員函數notify_one
其他線程調用notify_one()將wait的狀態喚醒後,wait恢復工作。
如果wait並沒有堵塞,那麼此時notify_one調用可能就沒有效果.
使用例子
class A
{
private:
list<int>msgqueue;
mutex mymutex1;
condition_variable mycon;//生成一個條件變量對象
public:
void MsgEnqueue()
{
int commmand = 0;
while (true)
{
unique_lock<mutex>l(mymutex1);
mycon.wait(l, [this]
{
if (!msgqueue.empty())
return true;
return false;
});
commmand = msgqueue.front();
msgqueue.pop_front();
l.unlock();//隨時unlock()
cout << "MsgEnqueue執行,取出一個元素 " << commmand << endl;
}
return;
}
void MsgDequeue()
{
for (int i = 0; i < 10000; ++i)
{
cout << "MsgDequeue執行,插入一個元素" << i << endl;
unique_lock<mutex>l(mymutex1);
msgqueue.push_back(i);
mycon.notify_one();//嘗試把wait()線程喚醒
}
}
};
int main()
{
A a;
thread t1(&A::MsgEnqueue, &a);
thread t2(&A::MsgDequeue, &a);
t1.join();
t2.join();
cout << endl;
}
condition_variable
成員函數notify_all
喚醒所有wait()