生产者消费者问题实践(头歌实验)第1关:生产者消费者问题实践,第2关:进程互斥和同步。
创始人
2024-01-30 00:07:14
0

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

题目:

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

任务:

相关知识

代码:

效果截图:

第2关:进程互斥和同步

任务

相关知识 

代码:

效果截图:

总结


题目:

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

任务:

    生产者—消费者之间设置一个具有n个缓存区的缓冲池,生产者进程将他所生产的产品放入一个缓冲区;消费者进程可以从一个缓冲区中取走产品去消费。不允许消费者进程到一个空缓冲去取产品。不允许生产者进程向一个已装满产品且尚未取走的缓冲区投放产品。使用多线程实现生产者和消费者问题模型,使用锁和信号量控制线程之间的同步。

相关知识

1.多线程相关的系统调用,

2.使用锁控制进程互斥,

3.使用信号量控制进程同步

多线程相关的系统调用

创建线程 pthread_create pthread_create(&thrd1, NULL, (void *)&thread_function, (void *) &some_argument); 线程创建函数包含四个变量,分别为:

1.一个线程变量名,被创建线程的标识

2. 线程的属性指针,缺省为NULL即可

3. 被创建线程的程序代码

4. 程序代码的参数

        线程等待 pthread_join pthread_create调用成功以后,新线程和老线程谁先执行,谁后执行用户是不知道的,这一块取决与操作系统对线程的调度,如果我们需要等待指定线程结束,需要使用pthread_join函数,这个函数实际上类似与多进程编程中的waitpid。 举个例子,以下假设 A 线程调用 pthread_join 试图去操作B线程,该函数将A线程阻塞,直到B线程退出,当B线程退出以后,A线程会收集B线程的返回码。 该函数包含两个参数:

 
  1. pthread_t th //th是要等待结束的线程的标识
  2. void **thread_return //指针thread_return指向的位置存放的是终止线程的返回状态。
  3. 调用实例:pthread_join(thrd1, NULL);

使用锁控制进程互斥

在主线程中初始化锁为解锁状态 pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL); 访问对象时的加锁操作与解锁操作 加锁 pthread_mutex_lock(&mutex) 释放锁 pthread_mutex_unlock(&mutex)

利用信号量实现进程同步

先引入头文件 #include 初始化信号量: int sem_init(sem_t \*sem, int pshared, unsigned int value); 成功返回0,失败返回-1 参数 sem:指向信号量结构的一个指针 pshared: 不是0的时候,该信号量在进程间共享,否则只能为当前进程的所有线程们共享 value:信号量的初始值 信号量减1操作,当sem=0的时候该函数会堵塞 int sem_wait(sem_t *sem); 成功返回0,失败返回-1 参数 sem:指向信号量的一个指针 信号量加1操作 int sem_post(sem_t *sem); 参数与返回同上 销毁信号量 int sem_destroy(sem_t *sem); 参数与返回同上

代码:

#include 
#include 
#include 
#include 
#include #define SIZE 10int in=0;
int out=0;
int buffer[SIZE];
sem_t empty;
sem_t full;
pthread_mutex_t mutex;void *Producer()
{int nextp=0;int i=0;for(; i <10; ++i){  int time = rand() % 10 + 1;usleep(time*100000); sem_wait(&empty); pthread_mutex_lock(&mutex);nextp = nextp + 1;buffer[in] = nextp;printf("Produce one message:%d\n", nextp);fflush(stdout);//printf后请一定调用这句刷新输出缓存in = (in + 1) % SIZE;pthread_mutex_unlock(&mutex);         //互斥锁解锁sem_post(&full);}
}void *Consumer()
{//请补充消费者线程函数代码int i=0;for(i=0;i<10;++i){int time=rand()%10+1;usleep(time*100000);sem_wait(&full);pthread_mutex_lock(&mutex);int nextc=buffer[out];out=(out+1)%SIZE;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(producid, NULL);   pthread_join(consumid, NULL);   sem_destroy(&empty);         //信号量的销毁sem_destroy(&full);    pthread_mutex_destroy(&mutex);   //互斥锁的销毁return 0;
}

效果截图:

第2关:进程互斥和同步

任务

     桌上有个能盛的下五个水果的空盘子。爸爸不停的向盘中放苹果或桔子,儿子不停的从盘中取出桔子享用,女儿不停的从盘中取出苹果享用。规定三人不能同时从盘中取放水果。试用信号量实现爸爸、儿子和女儿这三个进程之间的同步

相关知识 

1.多线程相关的系统调用

2.使用锁控制进程互斥

3.使用信号量控制进程同步

多线程相关的系统调用

include

创建线程 pthread_create pthread_create(&thrd1, NULL, (void *)&thread_function, (void *) &some_argument); 线程创建函数包含四个变量,分别为: 1.一个线程变量名,被创建线程的标识 2. 线程的属性指针,缺省为NULL即可 3. 被创建线程的程序代码 4. 程序代码的参数

线程等待 pthread_join pthread_create调用成功以后,新线程和老线程谁先执行,谁后执行用户是不知道的,这一块取决与操作系统对线程的调度,如果我们需要等待指定线程结束,需要使用pthread_join函数,这个函数实际上类似与多进程编程中的waitpid。 举个例子,以下假设 A 线程调用 pthread_join 试图去操作B线程,该函数将A线程阻塞,直到B线程退出,当B线程退出以后,A线程会收集B线程的返回码。 该函数包含两个参数: pthread_t th //th是要等待结束的线程的标识 void **thread_return //指针thread_return指向的位置存放的是终止线程的返回状态。 调用实例:pthread_join(thrd1, NULL);

代码:

#include 
#include 
#include 
#include 
#include 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; }
}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;
}

效果截图:

 

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了生产者消费者问题实践。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...