经典进程同步问题——生产者消费者问题

问题描述

“生产者—消费者”问题 (producer/consumer problem) 是最著名的进程同步问题。
该问题描述了共享固定大小缓冲区的两个线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。
与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。

它是许多相互合作进程的抽象,如输入进程与计算进程;计算进程与打印进程等。

要解决该问题,就必须让生产者在缓冲区满时休眠,等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。

设置两个资源信号量及一个互斥信号量。
资源信号量 empty:说明空缓冲区的数目,其初值为有界缓冲池的大小n。
资源信号量 full:说明满缓冲区的数目(即产品数目),其初值为 0。full+ empty= n。
互斥信号量 s: 说明该有界缓冲池是一个临界资源,必须互斥使用,其初值为 1。

semaphore full=0; /* 表示满缓冲区的数目 */
semaphore empty=n; /* 表示空缓冲区的数目 */
semaphore s=1; /* 表示对缓冲区进程操作的互斥信号量 */

代码实现

//生产者消费者问题
#include
#include
#include
#include
sem_t empty,full,s;
int buffer[10]={-1};
int fill=0;
int use=0;
void put(int value){
	buffer[fill]=value;
	fill=(fill+1)%11;
}
int get(){
	int tmp=buffer[use];
	use=(use+1)%11;
	return tmp;
}
void *producer(void *arg){
	printf("producer\n");

	int i=0;
	for(i=0;i<=20;i++){
		//sleep(3);
		sem_wait(&empty);
		sem_wait(&s);
		
		put(i);
		sem_post(&s);
		sem_post(&full);
		printf("producer put:%d\n",i);
	}

	//pthread_exit(0);
}
void *consumer(void *arg){
	printf("consumer\n");
	
	int i=0;
	for(i=0;i<=20;i++){
		//sleep(3);
		sem_wait(&full);
		sem_wait(&s);
		
		int tmp=get();
		
		sem_post(&s);
		sem_post(&empty);
		printf("consumer get:%d\n",tmp);
	}
	//pthread_exit(0);
}
int main(int argv,char * args[]){
	sem_init(&empty,0,10);
	sem_init(&full,0,0);
	sem_init(&s,0,1);
	pthread_t pro,con;
	pthread_create(&pro,NULL,producer,NULL);
	pthread_create(&con,NULL,consumer,NULL);
	pthread_join(con,NULL);
	pthread_join(pro,NULL);
	
	

}

你可能感兴趣的:(操作系统)