系列综述:
来源:该系列是主要参考《大话设计模式》和《设计模式(可复用面向对象软件的基础)》,其他详细知识点拷验来自于各大平台大佬的博客。
总结:设计模式汇总篇
如果对你有用,希望关注·点赞·收藏一波。
点此到文末惊喜↩︎
生产者
和消费者
对共享队列
访问的同步
问题(共享和互斥、同步和异步概念)#include
#include
#include
#include
#include
#include
using namespace std;
class MessageQueue {
public:
MessageQueue() {}
// 生产者放入消息队列中
void PushMsq(string msg) {
unique_lock<mutex> lock(mtx_);// 1.上锁:保证{}范围内的互斥访问
que_.push(msg); // 2.生产:向消息队列中添加消息
cv_.notify_one();// 3.唤醒:唤醒在该条件变量上等待队列优先级最高的一个线程
// m_cv.notify_all()会唤醒所有线程,但是会造成资源争用,要谨慎使用
}
// 消费者从消息队列中取出信息
string PopMsq() {
unique_lock<mutex> lock(mtx_);// 1. 上锁
// 2. 队列为空则等待:如果队列为空,等待生产者添加消息
while (que_.empty()) {
cv_.wait(lock);// 释放lock锁并阻塞等待
}
// 3. 消费:取出消息并返回
string msg = que_.front();
que_.pop();
return msg;
}
private:
mutex mtx_; // 互斥锁:保证消息队列和条件变量的互斥访问
queue<string> que_; // 消息队列:生产者和消费者的缓冲区
condition_variable cv_; // 条件变量:保证生产者和消费者的同步
};
// 定义生产者线程函数
void producer(MessageQueue& mq) {
for (int i = 0; i < 10; ++i) {
string msg = "message " + to_string(i);
mq.PushMsq(msg);
this_thread::sleep_for(chrono::milliseconds(100));
// 生产者线程休眠一段时间
}
}
// 定义消费者线程函数
void consumer(int id, MessageQueue& mq) {
for (int i = 0; i < 5; ++i) {
string msg = mq.PopMsq();
cout << "consumer " << id << " get message: " << msg << std::endl;
this_thread::sleep_for(chrono::milliseconds(200));
// 消费者线程休眠一段时间
}
}
// 测试生产者消费者模型
int main() {
MessageQueue msq;
thread t1(producer, ref(msq));
thread t2(consumer, 1, ref(msq));
thread t3(consumer, 2, ref(msq));
thread t4(consumer, 3, ref(msq));
t1.join();
t2.join();
t3.join();
t4.join();
return 0;
}
点此跳转到首行↩︎