通过信号量机制解决生产者-消费者问题的模拟程序
今天做操作系统实验,老师要求写一个小程序模拟用信号量解决生产者-消费者问题的过程,于是写了一个非常纠结的小程序,对信号量进行了大幅度的修改,虽然这样更容易看到每一步的运行结果,但是却让代码非常纠结,信号量也面目全非,承受能力比较强的童鞋们看一下吧。
对信号量的主要修改有:分离了记录型信号量和二进制信号量的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;
}
浙公网安备 33010602011771号