1、条件变量 condition_variable
条件变量:std::condition_variable wait() notify_one()
std::condition_variable 是一个类,需要等待一个条件达成。这个类需要和互斥量配合工作,用的时候需要生成这个类的对象;
只能唤醒一个线程
wait用于等待
如果第二个参数表达式是false,那么wait()将解锁互斥量,并堵塞到本行,等到其他线程调用notify_one()成员函数为止;
如果第二个参数返回true,那么wait()直接返回
当其他线程notify_one()将wait(睡眠/堵塞)的状态,此时堵塞将会被解开
(1)wait()会重新获取互斥量锁,如果获取不到互斥量的锁,就会卡在wait()这里,如果获取,流程继续往下走
(2)如果wait()有第二个参数,就判断这个表达式;如果表达式为false,那么wait()又对互斥量解锁,继续堵塞到本行;
如果表达式返回true,就返回,流程继续往下走(此时互斥锁被锁着)
如果wait()没有第二个参数,则wait()返回,流程往下走
如果wait()没有第二个参数 m_CVobj(uLockObj),没有第二参数,那么就跟第二个参数返回false效果一样(默认就是false)
#include <iostream>
#include <thread>
#include <list>
#include <mutex>
#include <windows.h>
using namespace std;
#define RUNFLAG 1
class dataShare
{
public:
dataShare() {
m_endMutex = true;
}
~dataShare() {}
// 存数据
void inMsgRecvQueue()
{
for (int i = 0; i < 1000; i++)
{
cout << "input list i:" << i << endl;
{
std::unique_lock<std::mutex> mutexObj1(m_Mutex);
m_RecvQueue.push_back(i);
m_CVobj.notify_one(); // 此时outMsgRecvQueue()中的wait()会被唤醒
}
}
m_endMutex = false;
}
bool outMsgQueue(int &num)
{
#if RUNFLAG
#else
if (!m_RecvQueue.empty())
{
std::unique_lock<std::mutex> mutexObj2(m_Mutex);
if (!m_RecvQueue.empty())
{
num = m_RecvQueue.front(); // 返回第一个元素,但是不检查元素是否存在;
m_RecvQueue.pop_front(); // 移除第一个元素但不反回
return true;
}
}
#endif
return false;
}
// 取数据
void outMsgRecvQueue()
{
int num;
#if RUNFLAG
while (m_endMutex)
{
std::unique_lock<std::mutex> uLockObj(m_Mutex);
m_CVobj.wait(uLockObj, [this] {
if (!m_RecvQueue.empty())
return true;
return false;
});
num = m_RecvQueue.front(); // 返回第一个元素,但是不检查元素是否存在;
m_RecvQueue.pop_front(); // 移除第一个元素但不反回
cout << "delet one data: " << num << " this thread id = " << std::this_thread::get_id() << endl;
uLockObj.unlock();
// doing something
}
#else
for (int i = 0; i < 1000; i++)
{
if (outMsgQueue(num))
{
cout << "delet one data" << num << endl;
}
else
{
cout << "outMsgRecvQueue no data" << endl;
}
}
#endif
cout << "end" << endl;
}
private:
std::list<int> m_RecvQueue;
bool m_endMutex; // 用于跳出while循环
//互斥量
std::mutex m_Mutex;
std::condition_variable m_CVobj;
};
int main()
{
dataShare datas;
std::thread inMsgObj(&dataShare::inMsgRecvQueue, &datas);
std::thread outMsgObj(&dataShare::outMsgRecvQueue, &datas);
inMsgObj.join();
outMsgObj.join();
system("pause");
return 0;
}