通过信号量机制解决生产者-消费者问题的模拟程序

  今天做操作系统实验,老师要求写一个小程序模拟用信号量解决生产者-消费者问题的过程,于是写了一个非常纠结的小程序,对信号量进行了大幅度的修改,虽然这样更容易看到每一步的运行结果,但是却让代码非常纠结,信号量也面目全非,承受能力比较强的童鞋们看一下吧。

  对信号量的主要修改有:分离了记录型信号量和二进制信号量的wait和signal操作,这样可以更方便的看出是在wait哪个信号量,而且给wait操作多加了一个参数,指示是生产者还是消费者在wait该信号量;为了简便,将信号量定义为int,没有使用阻塞队列,也没有忙等,最低只能减到0,不能减到-1,看起来似乎是整型信号量;没有实现block原语,在wait操作中通过调用Sleep(1)使得Windows帮我们堵塞线程,signal操作中自然也没有wakeup原语。总之,对信号量各种诡异的修改,改到面目全非。

#include <stdio.h>
#include <windows.h>

#pragma warning(disable:4996)			//disable warning C4996: 'freopen' was declared deprecated

//缓冲区大小
#define	BUFFER_SIZE	3

//缓冲区
int	buffer[BUFFER_SIZE];


//把缓冲区当作循环队列
//则下面分别是队尾和队头的索引下标
unsigned int	in = 0;
unsigned int	out = 0;



//信号量应定义为结构体,但是这里为了简单,使用了整型
typedef int	Semaphore;

//记录满缓冲区数量的记录型信号量
Semaphore	full = 0;

//记录空缓冲区数量的记录型信号量
Semaphore	empty = BUFFER_SIZE;

//保证对缓冲区进行互斥访问的互斥型信号量
Semaphore	mutex = 1;

//为了分辨到底是谁在wait信号量定义两个常量
#define PRODUCER	0
#define CONSUMER	1

//记录型信号量的wait操作
void waitS(int type, Semaphore *s)
{
	//等待不成功则输出信息,然后主动堵塞
	while (*s == 0)
	{
		if (type == PRODUCER)
		{
			printf("Producer is waiting for record semaphore......\n\n");
		}
		else if (type == CONSUMER)
		{
			printf("Consumer is waiting for record semaphore......\n\n");
		}
		//没有实现block原语,用Sleep函数吧
		Sleep(1);
	}

	//等待成功则执行这条语句
	(*s)--;
}

//互斥型信号量的wait操作,number用于指示是生产者还是消费者
void waitM(int type, Semaphore *s)
{
	//等待成功
	if (*s == 1)
	{
		(*s) = 0;
	}
	//等待不成功
	else
	{
		if (type == PRODUCER)
		{
			printf("Producer is waiting for mutex......\n\n");
		}
		else if (type == CONSUMER)
		{
			printf("Consumer is waiting for mutex......\n\n");
		}
		Sleep(1);
	}
}

//以下两个是signal操作,由于没有实现block原语,wakeup原语也就省略了

//记录型信号量的signal操作
void signalS(Semaphore *s)
{
	(*s)++;
}

//互斥型信号量的signal操作
void signalM(Semaphore *s)
{
	*s = 1;
}


//
//生产者
//
int __stdcall producer(LPVOID lpThreadParameter)
{
	int	nextp;

	while(1)
	{
		nextp = GetTickCount();
		printf("Produce an item.\n");
		waitS(PRODUCER,&empty);
		waitM(PRODUCER,&mutex);
		printf("Producer entered critical section.\n");
		buffer[in] = nextp;
		in = (++in) % BUFFER_SIZE;
		printf("After producer leaves critical section in = %d, out = %d, full = %d, empty = %d.\n",in,out,full+1,empty);
		signalM(&mutex);
		signalS(&full);
		printf("Producer left critical section.\n\n");
	}
	return 0;
}

//
//消费者
//
int __stdcall consumer(LPVOID lpThreadParameter)
{
	int	nextc;

	while(1)
	{
		waitS(CONSUMER,&full);
		waitM(CONSUMER,&mutex);
		printf("Consumer entered critical section.\n");
		nextc = buffer[out];
		out = (++out) % BUFFER_SIZE;
		printf("After consemer leaves critical section in = %d, out = %d, full = %d, empty = %d.\n",in,out,full,empty+1);
		signalM(&mutex);
		signalS(&empty);
		printf("Consumer left critical section.\n");
		printf("Consume an item.\n\n");
	}
	return 0;
}



int main()
{
	HANDLE	hProducer,hConsumer;

	//标准输出重定向到文件中,以方便查看运行过程
	freopen("D:\\stdout.txt","w",stdout);

	//创建生产者和消费者线程并立即运行
	hProducer = CreateThread(NULL,0,producer,NULL,0,NULL);

	hConsumer = CreateThread(NULL,0,consumer,NULL,0,NULL);

	//
	//执行0.5秒中自动退出
	//
	Sleep(500);

	TerminateThread(hProducer,0);
	TerminateThread(hConsumer,0);


	return 0;
}
posted @ 2011-04-26 21:48  pianoid  阅读(8519)  评论(0编辑  收藏  举报