信号量实现生产者消费者问题 window linux

 1. 在Windows操作系统上,利用Win32API提供的信号量机制,编写应用程序实现生产者——消费者问题。

2. 在Linux操作系统上,利用Pthread API提供的信号量机制,编写应用程序实现生产者——消费者问题。

3. 两种环境下,生产者和消费者均作为独立线程,并通过empty、full、mutex三个信号量实现对缓冲进行插入与删除。

4. 通过打印缓冲区中的内容至屏幕,来验证应用程序的正确性。

㈠设计思路

①声明三个信号量,互斥信号量mutex,计数信号量empty初始化值100,技术信号量full初始化值0,并声明一个缓冲区char类型的buffer数组,大小为10,初始值为N。

②produce利用信号量形成对buffer临界生产,添加一个元素进去,赋值为A。consume利用信号量形成对buffer临界消费,从buffer中拿出来一个元素,并将buffer中原来元素赋为B。每访问一次临界区,就输出buffer值。

③创建多线程,其中5个生产者,和5个消费者,每个线程最多操作缓冲区10次。

㈡流程图

 

声明一个char类型的数组buffer,大小为10,用来做生产者和消费者共同访问的共享变量,可视做临界区。

Win32下
#include <IOSTREAM.h>
#include <STDIO.H>
#include <windows.h>
HANDLE Empty,full,mutex;//声明3个信号量,互斥信号量mutex,计数信号量full和Empty
int x=0;
int y=0;
char *buffer;//缓冲区buffer
//输出buffer
void output()
{
	for (int i=0;i<10;i++)
	{
		cout<<buffer[i]<<" ";
	}
	cout<<"\n";
}
DWORD WINAPI produce(LPVOID param)
{
	int j=0;	
	do 
	{
		WaitForSingleObject(Empty,INFINITE);//buffer空余量减一
		WaitForSingleObject(mutex,INFINITE);//形成互斥,只能一个线程去生产
		cout<<GetCurrentThreadId()<<"^^^^^"<<j<<"^^^^^";
//输出当前线程的id号,和执行的次数
		buffer[(y++%10)]='A';//生产赋值为A
		output();//输出buffer
		j++;
		ReleaseSemaphore(mutex,1, NULL);//取消互斥,允许其他线程生产
		ReleaseSemaphore(full,1, NULL);//可以消费量加1
	} while (j!=10);//每个线程生产10次	
	return 0;
}
DWORD WINAPI consume(LPVOID param)
{	
	int j=0;	
	do 
	{
		WaitForSingleObject(full,INFINITE);//将可以消费量减1
		WaitForSingleObject(mutex,INFINITE);//形成互斥访问,自能一个线程可以访问。
			cout<<GetCurrentThreadId()<<"*****"<<j<<"*****";
		buffer[x++%10]='B';//消费时,赋值为B
		output();//输出buffer
		j++;
		ReleaseSemaphore(mutex,1, NULL);//取消互斥,允许其他线程消费
		ReleaseSemaphore(Empty,1, NULL);//buffer空余量加1		
	} while (j!=10);//每个线程可以消费10次
	return 0;
}
int main()
{
	int i;	
	Empty=CreateSemaphore(NULL,10,10,NULL);//声明计数信号量,Empty初值为10
	full=CreateSemaphore(NULL,0,10,NULL);//声明技术信号量,full初值为0
	mutex=CreateSemaphore(NULL,1,1,NULL);//申明互斥信号量,初值为1
//初始化buffer数组,大小为0	
	buffer=new char[10];
	for (i=0;i<10;i++)
	{
		buffer[i]='N';
	}	
//HANDLE thread;
	DWORD *ThreadId=(DWORD *)malloc(10*sizeof(DWORD*));
	HANDLE*ThreadHandle=(HANDLE)malloc(10*sizeof(HANDLE));//创建线程句柄,分配空间
	//创建5个生产者线程和5个消费者线程
	for (i=0;i<5;i++)
	{		ThreadHandle[i+5]=CreateThread(NULL,0,produce,NULL,0,&ThreadId[i+5]);			ThreadHandle[i]=CreateThread(NULL,0,consume,NULL,0,&ThreadId[i]);			
	}	
//让所有线程在主线程main()执行完钱全部执行完毕。
	WaitForMultipleObjects(10,ThreadHandle,TRUE,INFINITE);	
	return 0;
}

Linux下
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>

#define BUFFER_SIZE 10//缓冲区大小为10
char *buffer;
sem_t mutex,empty,full;//三个信号量,互斥信号量mutex,技术信号量empty和full
int x,y;//生产者和消费者在buffer中下标
void output()//输出buffer数组
{
	int i;
	for(i=0;i<BUFFER_SIZE;i++)
	{
		printf("%c",buffer[i]);
		printf(" ");
	}
	printf("\n");
}
void *produce()//生产者函数
{
	int j;
	j=0;	
	do
	{
		sem_wait(&empty);//buffer有空余部分,可以生产,并减一
		sem_wait(&mutex);//形成互斥访问,只能一个线程生产
		printf("%lu%s%d%s",pthread_self(),"^^^^^",j,"^^^^^ ");//输出当前线程的id号,以及正在执行的次数
		buffer[(x++)%BUFFER_SIZE]='A';//生产就赋值A
		output();//输出buffer
		j++;
		sem_post(&mutex);//取消互斥
		sem_post(&full);//生成完毕,增加一个可以消费量。
	}while (j!=30);//每个线程可以做30次
}
void *consume()//消费者函数
{
	int j;
	j=0;	
	do
	{
		sem_wait(&full);//可以消费的量减一
		sem_wait(&mutex);//互斥访问,只能一个线程消费
		printf("%lu%s%d%s",pthread_self(),"*****",j,"***** ");
		buffer[(y++)%BUFFER_SIZE]='B';//消费时,赋值为B
		output();//输出buffer值
		j++;
		sem_post(&mutex);//取消互斥,其他线程可以消费
		sem_post(&empty);//空余量加一
	}while (j!=30);//每个线程可以消费30次
}

int main()
{
	int i;
	x=0;
	y=0;
	buffer=(char*)malloc(BUFFER_SIZE*sizeof(char*));
	for(i=0;i<BUFFER_SIZE;i++)//初始化buffer数组,默认为N
	{
		buffer[i]='N';
	}
	//semaphore	
	sem_init(&mutex,1,1);//初始化互斥信号量mutex为1
	sem_init(&empty,0,BUFFER_SIZE);//初始化计数信号量empty为BUFFER_SIZE
	sem_init(&full,0,0);//初始化计数信号量full为0
	//multipthread
	pthread_t tid[10];
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	//创建5个生产者线程和5个消费者线程
	for(i=0;i<5;i++)
	{
		pthread_create(&tid[i],&attr,consume,NULL);
		pthread_create(&tid[i+5],&attr,produce,NULL);		
	}	
//让每个线程在主线程main执行前全部执行完毕。
	for(i=0;i<10;i++)
	{
		pthread_join(tid[i],NULL);
	}
	return 0;
}


 

 

 

 

 

 

 




  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值