头歌实验03:生产者消费者问题实践

第一关 :生产者消费者问题实践

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

#define SIZE 10

int in = 0;           //指示当前可以向缓冲区中写入消息的位置(即下一个空闲槽位)
int out = 0;            //指示当前取出消息的位置
int buffer[SIZE];       //用于存储生产者产生的消息
sem_t empty;    //信号量对象
sem_t full;
pthread_mutex_t mutex;  //声明一个互斥锁(mutex)

void *Producer()
{
    int nextp = 0;
    //用于跟踪将要生产(或放入缓冲区)的下一个消息的编号
    //这个编号随后被用作消息的内容
    int i = 0;
	for(; i < 10; ++i)
	{  
		int time = rand() % 10 + 1;
        //生成一个1到10之间的随机整数
                                usleep(time*100000); 
        //使用usleep函数暂停程序的执行,暂停时间为time乘以100000微秒,即0.1秒到1秒之间的一个随机时间,用于模拟程序执行中的随机延迟
                                sem_wait(&empty);   //用于对信号量进行操作
                                //empty > 0,调用者获取可用资源
                                //empty = 0,调用者被阻塞,直到empty变为正数
        

		pthread_mutex_lock(&mutex);
        //在访问共享资源之前,你需要获取(或“加锁”)互斥锁。
        //在持有互斥锁的情况下,你可以安全地访问共享资源。
        //如互斥锁已经被另一个线程持有,那么调用线程将被阻塞,直到互斥锁变得可用。
		nextp = nextp + 1;
		buffer[in] = nextp;
		printf("Produce one message:%d\n", nextp);
        //打印将要生产(或放入缓冲区)的下一个消息
		fflush(stdout);//printf后请一定调用这句刷新输出缓存
        //fflush(stdout); 被用于确保 printf() 输出的消息能够立即显示在上,而不是被缓存在缓冲区中等待后续输出或程序结束
		in = (in + 1) % SIZE;
		pthread_mutex_unlock(&mutex);         //互斥锁解锁
		sem_post(&full);        //通知可能正在等待的消费者线程有新的项可供消费
        //消费者线程在消费了一个项后,会调用sem_post(&empty);来通知生产者线程缓冲区中又有了一个空闲槽位
	}
}

void *Consumer()
{
	//请补充消费者线程函数代码
    int i = 0;
    for(; i < 10; i++)
    {
        int time = rand()%10 + 1;
        usleep(time*10000);
        sem_wait(&full);
        pthread_mutex_lock(&mutex);
        int nextc = buffer[out];
        out = out%SIZE + 1;
        printf("Consume one message:%d\n",nextc);
        fflush(stdout);
        pthread_mutex_unlock(&mutex);
        sem_post(&empty);
    }
}


int main()
{	
    sem_init(&empty, 0, 10);    //信号量初始化(最多容纳10条消息,容纳了10条生产者将不会生产消息)
	sem_init(&full, 0, 0);		
	pthread_mutex_init(&mutex, NULL);  //互斥锁初始化		
	pthread_t producid;	
	pthread_t consumid;		
	pthread_create(&producid, NULL, Producer, NULL);   //创建生产者线程	
	pthread_create(&consumid, NULL, Consumer, NULL);   //创建消费者线程	
    //如果我们需要等待指定线程结束,需要使用pthread_join函数
	pthread_join(producid, NULL); 	
	pthread_join(consumid, NULL);   
	sem_destroy(&empty);         //信号量的销毁
	sem_destroy(&full);    
	pthread_mutex_destroy(&mutex);   //互斥锁的销毁
	return 0;
}

 

第二关:进程互斥和同步

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>


sem_t apple;
sem_t orange;
sem_t empty;
pthread_mutex_t mutex;

void *Dad() //爸爸相当于生产者
{
	int nextp = 0;
	int i = 0;
    for(i = 0; i < 10; ++i)
	{
		int time = rand() % 10 + 1;          //随机使程序睡眠0点几秒
		usleep(time*100000);        
		sem_wait(&empty); //操作信号量
		pthread_mutex_lock(&mutex); //加锁
		if(nextp == 0)
		{
			printf("爸爸放入了一个苹果\n");
		}
		else
		{
			printf("爸爸放入了一个桔子\n");
		}
        fflush(stdout); //刷新
		
		pthread_mutex_unlock(&mutex);         //互斥锁解锁
		
		if(nextp == 0)
		{
			sem_post(&apple);
		}
		else
		{
			sem_post(&orange);
		} 
		nextp = 1 - nextp; 
        //该行代码决定了nextp只会是0 or 1
	}
}

void *Daughter()
{
	while(1)
	{
		int time = rand() % 10 + 1;          //随机使程序睡眠0点几秒
		usleep(time * 100000);        
		sem_wait(&apple); 
		pthread_mutex_lock(&mutex);
		printf("女儿取了一个苹果\n") ;
        fflush(stdout);
		pthread_mutex_unlock(&mutex);         //互斥锁解锁
		sem_post(&empty);
	}
}

void *Son()
{
	//请添加儿子线程的函数代码
    while(1)
    {
        int time = rand() % 10 + 1;          //随机使程序睡眠0点几秒
		usleep(time * 100000);        
		sem_wait(&orange); 
        pthread_mutex_lock(&mutex);
		printf("儿子取了一个桔子\n") ;
        fflush(stdout);
		pthread_mutex_unlock(&mutex);         //互斥锁解锁
		sem_post(&empty);
    }
}


int main()
{			
    sem_init(&empty, 0, 5);    //信号量初始化
	sem_init(&orange, 0, 0);
	sem_init(&apple, 0, 0);		
	pthread_mutex_init(&mutex, NULL);  //互斥锁初始化		
	pthread_t dadid;	
	pthread_t daughterid;
	pthread_t sonid;		
	pthread_create(&dadid, NULL, Dad, NULL);   //创建爸爸线程	
	pthread_create(&daughterid, NULL, Daughter, NULL);   //创建女儿线程
	pthread_create(&sonid, NULL, Son, NULL);   //创建儿子线程		
	pthread_join(daughterid, NULL);
	pthread_join(sonid, NULL);   
	
	sem_destroy(&empty);         //信号量的销毁
	sem_destroy(&apple);
	sem_destroy(&orange);    

	

	pthread_mutex_destroy(&mutex);   //互斥锁的销毁

	

	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值