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