【实验七】Linux生产者消费者问题(线程)

目录

一、问题介绍

二、代码

1、prod_cons.cpp

2、producer.h

3、producer.cpp

4、consumer.h 

5、consumer.cpp

6、mq.h

7、mq.cpp 

8、message.h

9、message.cpp

10、pc.mk 

三、运行结果

一、问题介绍

生产者消费者问题(英语: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

三、运行结果

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生产者消费者问题是一个经典的同步问题,它通常在多线程或多进程的环境中出现。在Linux下,可以使用信号量或互斥锁等机制来解决这个问题。 具体来说,生产者消费者问题涉及到两个角色:生产者和消费者。生产者负责生成产品并将其放入缓冲区,而消费者则负责从缓冲区中取出产品并消费它们。由于缓冲区大小有限,当缓冲区满时,生产者必须等待消费者取出一些产品。同样地,当缓冲区为空时,消费者必须等待生产者生成一些产品。 在Linux下,可以使用信号量来解决这个问题。具体来说,可以使用两个信号量:一个用于表示缓冲区中可用的空间数量,另一个用于表示缓冲区中已经存储的产品数量。当生产者生成一个产品时,它将首先获取空间信号量,以确保缓冲区中有足够的空间来存储这个产品。然后,它将产品放入缓冲区,并释放产品信号量。当消费者取出一个产品时,它将首先获取产品信号量,以确保缓冲区中有产品可供消费。然后,它将从缓冲区中取出产品,并释放空间信号量。 除了信号量,还可以使用互斥锁来解决生产者消费者问题。具体来说,可以使用一个互斥锁来保护缓冲区,以确保同一时间只有一个线程可以访问它。然后,可以使用两个条件变量:一个用于表示缓冲区中可用的空间数量,另一个用于表示缓冲区中已经存储的产品数量。当生产者生成一个产品时,它将首先获取互斥锁,并检查空间条件变量以确保缓冲区中有足够的空间来存储这个产品。如果没有足够的空间,它将等待空间条件变量。然后,它将产品放入缓冲区,并发出产品条件变量以通知消费者。当消费者取出一个产品时,它将首先获取互斥锁,并检查产品条件变量以确保缓冲区中有产品可供消费。如果没有产品可供消费,它将等待产品条件变量。然后,它将从缓冲区中取出产品,并发出空间条件变量以通知生产者。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值