问题的提出:
生产者-消费者(producer-consumer)问题是一个著名的进程同步问题。它描述的是:有一群生产者进程在生产产品,并将这些产品提供给消费者进程去消费。为使生产者进程与消费者进程能并发执行,在两者之间设置了一个具有n个缓冲区的缓冲池,生产者进程将其所生产的产品放入一个缓冲区中;消费费者进程可从一个缓冲区中取走产品去消费。尽管所有的生产者进程和消费者进程都是以异步方式运行的,但它们之间必须保持同步,既不允许消费者进程到一个空缓冲区去取产品,也不允许生产者进程向一个已装满产品且尚未被取走的缓冲区中投放产品。
目录
一、预备知识
1、进程管理
2、互斥量
二、目的
1.了解信号量的使用。
2.加深对信号量机制的理解。
三、要求
1.理解生产者与消费者问题模型,掌握解决该问题的算法思想。
2.掌握正确使用同步机制的方法。
四、实验内容
1.问题描述
2.功能要求
五、实现代码
运行结果
编辑
参考文献
一、预备知识
1、进程管理
进程:进程是指一个具有一定独立功能的程序在一个数据集合上的一次动态执行过程。
进程管理:操作系统的职能之一,主要是对处理机进行管理。为了提高CPU的利用率而采用多道程序技术。通过进程管理来协调多道程序之间的关系,使CPU得到充分的利用。
2、互斥量
互斥量(mutex)是c++中提供的一个类,就像一把锁,当有人使用某个资源时,就将锁锁上,使用完毕就将锁打开。
二、目的
1.了解信号量的使用。
2.加深对信号量机制的理解。
三、要求
1.理解生产者与消费者问题模型,掌握解决该问题的算法思想。
2.掌握正确使用同步机制的方法。
四、实验内容
1.问题描述
一组生产者向一组消费者提供消息,它们共享一个有界缓冲池,生产者向其中投放消息,消费者从中取得消息。假定这些生产者和消费者互相等效,只要缓冲池未满,生产者可将消息送入缓冲池,只要缓冲池未空,消费者可从缓冲池取走一个消息。
2.功能要求
根据进程同步机制,编写一个解决上述问题的程序,可显示缓冲池状态、放数据、取数据等过程。
五、实现代码
#include<thread>
#include<iostream>
#include<mutex>
#include<list>
#include<vector>
using namespace std;
int exit_thread = 0;//执行完的线程数目
const int producer_int = 10;//生产者数量
const int consumer_int = 10;//消费者数量
list<int>buffer;//这里用int 类型代替要生产的东西(类似于编号)
mutex public_mutex;//缓冲池互斥信号量
//防止producer生产到一半时consumer就访问读取导致数据损坏
void producer()//模拟生产者进程
{
mutex producer_mutex;//生产者内部互斥量
//unique_lock<mutex>a(producer_mutex, defer_lock);
//unique_lock<mutex>b(public_mutex, defer_lock);
int m;
//if (a.try_lock() && b.try_lock())
//{
lock(producer_mutex, public_mutex);
lock_guard<mutex>a(producer_mutex, adopt_lock);
lock_guard<mutex>b(public_mutex, adopt_lock);
cout << "**************************" << endl;
cout << "现在运行的消费者线程id是:" << this_thread::get_id() << endl;
cout << "请输入你要生产的产品编号:";
cin >> m;
if (buffer.size() != 10)
{
buffer.push_back(m);
cout << "**************************" << endl;
cout << "当前缓冲池的情况如下:" << endl;
for (auto i = buffer.begin(); i != buffer.end(); ++i)
{
cout << *i << endl;
}
cout << "**************************" << endl;
exit_thread++;
//producer_mutex.unlock();
//public_mutex.unlock();
return;
}
else
{
cout << "缓冲池已经满了无法生产东西" << endl;
cout << "**************************" << endl;
cout << "当前缓冲池的情况如下:" << endl;
for (auto i = buffer.begin(); i != buffer.end(); ++i)
{
cout << *i << endl;
}
cout << "**************************" << endl;
exit_thread++;
//producer_mutex.unlock();
//public_mutex.unlock();
return;
}
//}
}
void consumer()//模拟消费者进程
{
mutex consumer_mutex;
//unique_lock<mutex>a(consumer_mutex, defer_lock);
//unique_lock<mutex>b(public_mutex, defer_lock);
//if (a.try_lock() && b.try_lock())
//{
lock(consumer_mutex, public_mutex);
lock_guard<mutex>a(consumer_mutex, adopt_lock);
lock_guard<mutex>b(public_mutex, adopt_lock);
cout << "**************************" << endl;
cout << "现在运行的消费者线程id是:" << this_thread::get_id() << endl;
if (buffer.size() != 0)
{
cout << "读取的数据为:" << buffer.front() << endl;
buffer.pop_front();
cout << "**************************" << endl;
cout << "当前缓冲池的情况如下:" << endl;
for (auto i = buffer.begin(); i != buffer.end(); ++i)
{
cout << *i << endl;
}
cout << "**************************" << endl;
exit_thread++;
//consumer_mutex.unlock();
//public_mutex.unlock();
return;
}
else
{
cout << "缓冲池没有任何产品无法读取产品!!" << endl;
cout << "**************************" << endl;
cout << "当前缓冲池的情况如下:" << endl;
for (auto i = buffer.begin(); i != buffer.end(); ++i)
{
cout << *i << endl;
}
cout << "**************************" << endl;
exit_thread++;
//consumer_mutex.unlock();
//public_mutex.unlock();
return;
}
//}
}
void displaybuffer()//显示缓冲池情况
{
cout << "当前缓冲池的情况如下:" << endl;
for (auto i = buffer.begin(); i != buffer.end(); ++i)
{
cout << *i << endl;
}
cout << "**************************" << endl;
}
int main()
{
//vector<thread>t_producer;
thread t_producer[producer_int];
//vector<thread>t_consumer;
thread t_consumer[consumer_int];
for (int i = 0; i < producer_int; ++i)
{
t_producer[i] = thread(producer);
t_producer[i].detach();
}
for (int i = 0; i < consumer_int; ++i)
{
t_consumer[i] = thread(consumer);
t_consumer[i].detach();
}
while (1)//防止detach后的进程在主函数结束后还没结束导致异常
{
if (exit_thread == (producer_int + consumer_int))
break;
}
displaybuffer();
cout << "实验完成" << endl;
return 0;
}
运行结果
参考文献
1、百度文库
2、具体的线程知识可以观看这个网站学习
这个程序可能有点简陋,漏洞有点多,各位大佬如果有什么指正的地方可以在评论区指出,谢谢!!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)