目录
1 实验名称
进程的同步和互斥
2 实验目的
通过编写程序实现进程的同步和互斥,使学生学会分析进程(线程)竞争资源现象,学习通过信号量解决进程互斥的方法。
3 实验内容
编写C程序,实现多线程模拟生产者、消费者问题,给出测试数据,记录程序运行结果,完成实验报告。要求:
(1)设置存放产品的缓冲区的个数为6个。
(2)信号量机制实现生产者和消费者对缓冲区的互斥访问。
(3)生产者生产产品时,要输出当前缓冲区冲产品的个数和存放产品的位置。
(4)消费者消费产品时,要输出当前缓冲区冲产品的个数和消费产品的位置。
(5)用多线程的并发实现生产者进程和消费者进程的同步。
4 实验原理及流程图
利用信号量机制解决进程(线程)的基本方法。
为使生产者进程与消费者进程能并发执行,在两者之间设置了一个具有 n 个缓冲区的缓冲池:生产者进程从文件中读取一个数据,并将它存放到一个缓冲区中;消费者进程从一个缓冲区中取走数据,并输出此数据。生产者和消费者之间必须保持同步原则:不允许消费者进程到一个空缓冲区去取产品;也不允许生产者进程向一个已装满产品且尚未被取走的缓冲区中投放产品。
1.关系分析:生产者和消费者对缓存区访问时互斥关系;生产者生产内容后,消费者才能消费是同步关系。
2.信号量设置:
(1)互斥信号量 mutex,控制缓存区的互斥访问,初始值为 1。
(2)同步信号量 full,记录缓存区中已使用的数,初始值为 0。
(3)同步信号量 empty,记录缓存区未使用的数,初始值为 N。
3.PV 操作在同步和互斥的应用:
(1)同步问题:如果某行为要使用某种资源,就在行为之前 P 操作该资源;如果某行为会提供某种资源,就在行为之后 V 操作该资源。
(2)互斥问题:P、V 操作要和使用互斥资源的行为紧密结合使用。
4.同步与互斥的区别:
(1)同步是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。
(2)互斥是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。
5 实验源代码
#include<iostream>
#include<queue>
#include<list>
#include<cstdlib>
#include<ctime>
using namespace std;
typedef struct
{
int type;//进程类型标号 0 生产者 1位消费者
int ID;//进程系统号 1-10
int state;//进程状态 0就绪 1等待 2完成
char product;//进程产品 字符
}PCB;
int buffersize = 6;//缓冲区大小
queue<PCB>ready;
queue<PCB>producerwait;//生产者等待队列
queue<PCB>consumerwait;//消费者等待队列
list<PCB>over;//收集已经运行结束的进程
int buffercount = 0;
int buffer[6];
void Producer(PCB &p)
{
if (buffercount < 6)
{
buffercount++;
buffer[buffercount] = p.ID;
if (!consumerwait.empty())
{
PCB temp;
temp = consumerwait.front();
temp.state = 0;
ready.push(temp);
consumerwait.pop();
}
over.push_back(p);
p.state = 2;
}
else
{
p.state = 1;
producerwait.push(p);
}
}
void Consumer(PCB &p)
{
if (buffercount != 0)
{
buffer[buffercount] = NULL;
buffercount--;
over.push_back(p);
if (!producerwait.empty())
{
PCB temp;
temp = producerwait.front();
temp.state = 0;
ready.push(temp);
producerwait.pop();
}
p.state = 2;
}
else
{
p.state = 1;
consumerwait.push(p);
}
}
int main()
{
PCB p[10];
for (int i = 0; i < 10; i++)//对模块进行初始化
{
p[i].type = rand() % 2;
p[i].ID = i + 1;
p[i].state = 0;
p[i].product = 'a'+i;
ready.push(p[i]);
}
while (!ready.empty())
{
PCB t;
t = ready.front();
ready.pop();
if (t.type == 0)//如果是生产者
{
Producer(t);
}
else
{
Consumer(t);
}
cout << "****************就绪队列:****************" << endl;
queue<PCB>_ready;
_ready = ready;
while (!_ready.empty())
{
PCB te = _ready.front();
cout <<"进程类型标号: "<< te.type<<" 进程系统号: "<<te.ID<<" 进程状态: "<<te.state<<" 进程产品: "<<te.product<<" " << endl;
_ready.pop();
}
cout << "****************完成链表:****************" << endl;
std::list<PCB>::iterator iter;
std::list<PCB>::iterator start = over.begin();
for(iter=over.begin();iter!=over.end();iter++)
{
PCB p = *iter;
cout << "进程类型标号: " << p.type << " 进程系统号: " << p.ID << " 进程状态: " << p.state << " 进程产品: " << p.product << " " << endl;
}
cout << "****************生产者等待队列:****************" << endl;
queue<PCB>_producerwait;
_producerwait = producerwait;
while (!_producerwait.empty())
{
PCB te = _producerwait.front();
cout << "进程类型标号: " << te.type << " 进程系统号: " << te.ID << " 进程状态: " << te.state << " 进程产品: " << te.product << " " << endl;
_producerwait.pop();
}
cout << "****************消费者等待队列:****************" << endl;
queue<PCB>_consumerwait;
_consumerwait = consumerwait;
while (!_consumerwait.empty())
{
PCB te = _consumerwait.front();
cout << "进程类型标号: " << te.type << " 进程系统号: " << te.ID << " 进程状态: " << te.state << " 进程产品: " << te.product << " " << endl;
_consumerwait.pop();
}
cout << endl;
cout << endl;
}
system("pause");
return 0;
}