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


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

      对信号量的主要修改有:分离了记录型信号量和二进制信号量的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;
    }
    
  • 相关阅读:
    HDU3336 Count the string(kmp
    HDU2087 剪花布条(字符串...半暴力写的?
    HDU4763 Theme Section(kmp
    HDU1251 统计难题(字典树|map
    HDU1305 Immediate Decodability (字典树
    priority_queue member function
    HDU
    洛谷 P3370 【模板】字符串哈希 (set||map||哈希||字典树(mle)
    mysql (master/slave)复制原理及配置
    mysql备份小记
  • 原文地址:https://www.cnblogs.com/pianoid/p/2029795.html
Copyright © 2020-2023  润新知