第一版代码:
#include <list>
#include <iostream>
#include <memory>
#include <mutex>
#include <thread>
using namespace std;
class A {
public:
void inMsgRecvQueue() {
for (int i = 0; i < 10000; i++) {
unique_lock<std::mutex> ulk(mtx);
msgRecvQueue.push_back(i);
}
}
bool outMsgLULProc(int& cmd) {
unique_lock<std::mutex> ulk(mtx);
if(!msgRecvQueue.empty()) {
cmd = msgRecvQueue.front();
msgRecvQueue.pop_front();
return true;
}
return false;
}
void outMsgRecvQueue() {
int cmd;
for (int i = 0; i < 10000; i++) {
bool res = outMsgLULProc(cmd);
if (res == true) {
// 处理
} else {
cout << "消息队列为空" << endl;
}
}
}
private:
std::list<int> msgRecvQueue;
mutex mtx;
};
int main() {
A obj;
thread my_t_out_obj(&A::outMsgRecvQueue, &obj);
thread my_t_in_obj(&A::inMsgRecvQueue, &obj);
my_t_out_obj.join();
my_t_in_obj.join();
return 0;
}
第二版代码:改为双重锁定:优化了一步
bool outMsgLULProc(int& cmd) {
if(!msgRecvQueue.empty()) {
unique_lock<std::mutex> ulk(mtx);
if(!msgRecvQueue.empty()) {
cmd = msgRecvQueue.front();
msgRecvQueue.pop_front();
return true;
}
}
return false;
}
第三版代码:引入条件变量(类),与互斥量配合工作
#include <list>
#include <iostream>
#include <memory>
#include <mutex>
#include <thread>
#include <condition_variable>
using namespace std;
class A {
public:
void inMsgRecvQueue() {
for (int i = 0; i < 10000; i++) {
unique_lock<std::mutex> ulk(mtx);
msgRecvQueue.push_back(i);
my_cond.notify_one(); // 尝试唤醒等待中的线程。解锁由unique_lock完成
}
}
void outMsgRecvQueue() {
int cmd;
while(true) {
unique_lock<std::mutex> ulk(mtx);
// 等待notify_one()来通知,相当于while死循环
// wait被唤醒之后:尝试不断获取并加锁互斥量。获取不到,则反复尝试。
// 获取到互斥量后:加锁互斥量
// 如果lambda表达式为true:wait返回
// 如果lambda表达式为false:互斥量解锁,重新等待唤醒
// 如果wait没有第二个参数【等价于】第二个参数为lambda表达式且返回false效果相同
// 解锁互斥量并堵塞到这行,堵到其他线程调用notify_one()的通知为止
my_cond.wait(ulk, [this]()->bool{
if(!msgRecvQueue.empty()) {
return true;
}
return false;
});
}
}
private:
std::list<int> msgRecvQueue;
mutex mtx;
condition_variable my_cond;
};
int main() {
A obj;
thread my_t_out_obj(&A::outMsgRecvQueue, &obj);
thread my_t_in_obj(&A::inMsgRecvQueue, &obj);
my_t_out_obj.join();
my_t_in_obj.join();
return 0;
}
调用过`notify_one()`之后,wait被唤醒。
a、wait不断尝试重新获取