目录
一、问题介绍
生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
二、代码
1、prod_cons.cpp
#include<thread>
#include"mq.h"
#include"producer.h"
#include"consumer.h"
int main(int argc,char* argv[]){
MQ mq;
std::thread p(producer,std::ref(mq));
std::thread c(consumer,std::ref(mq));
p.join();
c.join();
return 0;
}
2、producer.h
#include"mq.h"
void producer(MQ& mq);
3、producer.cpp
#include<string.h>
#include"producer.h"
#include"message.h"
void producer(MQ& mq){
while(true){
Message m;
memset(&m,0,sizeof(m));
std::cout<<"please enter expression:";
std::cin>>m;
mq.put(m);
}
}
4、consumer.h
#include"mq.h"
void consumer(MQ& mq);
5、consumer.cpp
#include<iostream>
#include<fstream>
#include"consumer.h"
#include"message.h"
void process(Message& m){
switch(m.op){
case 0:
m.res=m.oprand1+m.oprand2;
break;
case 1:
m.res=m.oprand1-m.oprand2;
break;
case 2:
m.res=m.oprand1*m.oprand2;
break;
case 3:
if(m.oprand2!=0){
m.res=m.oprand1/m.oprand2;
}else{
m.status='F';
}
break;
default:
m.status='N';
break;
}
std::ofstream fout ("log.txt",std::ios::app);
fout<<m<<std::endl;
fout.close();
}
void consumer(MQ& mq){
while(true){
Message m=mq.get();
process(m);
}
}
6、mq.h
#pragma once
#include<queue>
#include<mutex>
#include<condition_variable>
#include"message.h"
class MQ{
public:
void put(Message m);
Message get();
private:
std::queue<Message> q;
std::mutex mu;
std::condition_variable non_empty;
};
7、mq.cpp
#include"mq.h"
void MQ::put(Message m){
std::lock_guard<std::mutex> lk(mu);
q.push(m);
non_empty.notify_one();
}
Message MQ::get(){
std::unique_lock<std::mutex> ul(mu);
while(q.empty()){
non_empty.wait(ul);
}
Message m=q.front();
q.pop();
return m;
}
8、message.h
#pragma once
#include<iostream>
struct Message{
int oprand1;
int op;
int oprand2;
int res;
char status;
};
std::istream &operator >>(std::istream& in, Message& m);
std::ostream &operator <<(std::ostream& out,const Message& m);
9、message.cpp
#include"message.h"
std::istream& operator >>(std::istream& in ,Message& m){
in>>m.oprand1>>m.op>>m.oprand2;
m.status='S';
return in;
}
std::ostream& operator <<(std::ostream& out ,const Message& m){
char ops[]={'+','-','*','/'};
if(m.status=='S'){
out<<m.oprand1<<ops[m.op]<<m.oprand2<<"="<<m.res;
}else if(m.status=='F'){
out<<"The divisor cannot be 0";
}else if(m.status=='N'){
out<<"Opreator iuput error";
}
return out;
}
10、pc.mk
GCC=g++
CFLAG=-c
OFLAG=-o
LIB=-pthread
EXE=prod_cons
OBJ=prod_cons.o producer.o consumer.o mq.o message.o
${EXE}:${OBJ}
${GCC} ${OFLAG} $@ $^ ${LIB}
%.o:%.cpp
${GCC} ${CFLAG} $^
clean:
rm *.o