生产者消费者问题实践(头歌实验)第1关:生产者消费者问题实践,第2关:进程互斥和同步。

news2025/8/14 3:50:12

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

目录

题目:

第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 <semaphore.h> 初始化信号量: 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 <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;

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.h>

创建线程 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 <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; 
	}
}

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

效果截图:

 

总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/14947.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux的命令行

命令行的格式 command [-options] [parameter] options和parameter并不是每一个的命令都需要的 ls命令 直接的ls 查看当前文件目录下的所有文件以及文件夹 ls -a 查看所有的同时&#xff0c;查看隐藏的文件&#xff0c;在Linux中以.开头的文件都会被隐藏起来 ls -l 以…

【Java学习笔记】第四章 面向对象编程三部曲(上)

【Java学习笔记】第四章 面向对象编程三部曲&#xff08;上&#xff09; 【Java学习笔记】第四章 面向对象编程三部曲&#xff08;中&#xff09; 【Java学习笔记】第四章 面向对象编程三部曲&#xff08;下&#xff09; 文章目录4.面向对象编程&#xff08;上&#xff09;4.…

Kafka 插件并创建 Kafka Producer 发送

相关说明 启动测试前清空所有数据。每次测试先把所有数据写入 Kafka&#xff0c;再加载 Kafka 插件同步数据到 DolphinDB 中。目的是将同步数据的压力全部集中到 Kafka 插件。以 Kafka 插件从收到第一批数据到收到最后一批数据的时间差作为同步数据的总耗时。 测试流程 加载 …

公网远程连接内网Everything实现快速搜索私有云文件

企业外派出差&#xff0c;已经是稀松平常的事&#xff0c;通常出差的同事都会带一个优盘或移动硬盘。但优盘和硬盘是离线设备&#xff0c;所存储的文件数据无法及时更新&#xff0c;因此能够连接公司主机获得最新文件才是出差的首选。可是公司主机位于内网&#xff0c;且面对浩…

【搭建NextCloud私有云盘服务】采用docker在linux上进行部署,内含nextCloud移植(迁移服务器)方法

1、前言 完成的效果&#xff1a; 在linux上搭建NextCloud云盘服务&#xff0c;可以通过域名访问到云盘服务&#xff0c;并且安装有SSL证书&#xff0c;可进行https访问。 例如&#xff1a; 服务器公网ip为47.110.66.88 域名为&#xff1a;test.huahua.com 可直接通过访问https…

Java#10(String 类的构造方法和练习)

目录 一.String类的构造方法 1.public String()空参构造 2.public String(char[ ] ch2);(对堆区已有的值没有办法复用,数据多会浪费内存空间,而直接赋值如果已有相同数据可以复用,不会在浪费太多内存) 3.public String(byte[ ] bytes) 二.字符串的比较 1.前提基础: 比较…

解决使用svg绘制后下载图片以及下载svg内部嵌套image图片失败的问题。

在使用svg进行图形绘制之后&#xff0c;可能需要下载已经绘制的svg图片&#xff0c;我们可能会遇到以下两种情况&#xff1a; 情况1&#xff1a; <svg width"640" height"400" xmlns"http://www.w3.org/2000/svg" id"svgColumn">…

解决问题 - 错误:不支持发行版本 5

文章目录一、提出问题二、解决问题&#xff08;一&#xff09;设置项目SDK与语言等级&#xff08;二&#xff09;设置模块语言等级&#xff08;三&#xff09;设置Java编译器等级&#xff08;四&#xff09;运行程序&#xff0c;测试问题是否已解决一、提出问题 基于JDK11创建…

阿里Redis最全面试全攻略,读完这个就可以和阿里面试官好好聊聊

简述Redis常用的数据结构及其如何实现的&#xff1f; Redis支持的常用5种数据类型指的是value类型&#xff0c;分别为&#xff1a;字符串String、列表List、哈希Hash、集合Set、有序集合Zset&#xff0c;但是Redis后续又丰富了几种数据类型分别是Bitmaps、HyperLogLogs、GEO。…

年搜索量超 7 亿次背后:这款 APP 用火山引擎 DataTester 完成“数据驱动”

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 双十一刚过&#xff0c;双十二在即&#xff0c;随着线上营销玩法的层出不穷&#xff0c;各平台之间的价格逐渐“内卷”。消费者对跨平台比价的需求越来越强烈&#…

【实时语音转文本】PC端实时语音转文本(麦克风外音系统内部音源)

语音转文字这个功能可以应用在视频动态字幕&#xff0c;语音快速输入&#xff0c;实时记录通话内容&#xff0c;高级应用可以在人工智能&#xff0c;语音识别&#xff0c;智能助手方面&#xff0c;还需要一点机器学习可以做出一些好玩的东西&#xff0c;比如PC端AI助理&#xf…

给开源项目做一个漂亮简洁的版本迭代更新图,生成固定链接复制到介绍中、公众号菜单链接中、博客中和网页中等

背景 开源项目的版本迭代与更新经常需要更新迭代文档&#xff0c;但是readme.md没有比较美观一点的效果&#xff0c;所以文本分享一种第三方的方式&#xff1a;用TexSpire的免费在线文档分享功能&#xff0c;手机、PC、Pad都可以适配。 效果预览 使用 视频教程 第一步&…

重磅 | 思特威获得ISO 26262:2018汽车功能安全ASIL D流程认证证书

确保安全是汽车制造商和系统供应商的责任。为了从芯片IP级开始解决功能安全问题&#xff0c;国际标准化组织&#xff08;ISO&#xff09;在2018年追加了汽车半导体的功能安全评估指南。 彼时&#xff0c;新车搭载的芯片数量、种类以及软件代码行数开始呈现倍数增长。按照ISO 2…

重磅!华秋电子再次入选“中国产业数字化百强榜”

11月16日&#xff0c;由江苏省商务厅、南京市人民政府指导&#xff0c;南京市商务局主办的江苏电子商务大会暨第九届中国产业数字化年会在南京开幕。 据了解&#xff0c;会议上公开发布了“2022中国产业数字化百强榜”&#xff0c;这也是托比网自2015年以来发布的第13个榜单。榜…

ES6解构赋值及ES6的一些简写介绍

1、ES6解构赋值&#xff1a; ● 解构赋值&#xff0c;就是快速地从对象或者数组中取出成员的一个语法方式 (1) 解构数组&#xff1a; ● 快速从数组中获取成员 <script>//ES5的方式从数组中获取成员var arr [Jack,Rose,Tom]var a arr[0] //Jackvar b arr[1] //Ro…

实验六 数组(山东建筑大学)

第1关:实验6.1 任务描述 输入3个整数,按由大到小的顺序输出。 输入样例 1 1 2 3 输出样例 1 3 2 1 开始你的任务吧,祝你成功! 第2关:实验6.2 任务描述 输入10个整数,将其中最小的数与第一个数对换,把最大的数与最后一个数对换。 输入样例 1 2 1 3 4 5 6 7 8 10 9 输…

感性认识一下Linux的进程地址空间和写时拷贝技术

虽然本篇文章对操作系统的理解不怎么深入&#xff0c;或者说仅仅是一些皮毛知识(也可能皮毛也算不上)&#xff0c;但还是需要读者有一些Linux的基础理解&#xff0c;如何确定是否有这些基础呢&#xff1f;可以参考我的这一篇博客&#xff1a;Linux —— 进程概念超详解! 1.“奇…

LeetCode 318 周赛

2460. 对数组执行操作 给你一个下标从 0 开始的数组 nums &#xff0c;数组大小为 n &#xff0c;且由 非负 整数组成。 你需要对数组执行 n - 1 步操作&#xff0c;其中第 i 步操作&#xff08;从 0 开始计数&#xff09;要求对 nums 中第 i 个元素执行下述指令&#xff1a;…

阿里 P8 架构师力荐 java 程序员人手一套 116 页 JVM 吊打面试官专属秘籍

只要是 java 程序员&#xff0c;肯定对于 JVM 来说并不陌生&#xff0c;甚至是从熟悉到陌生&#xff0c;为什么这样说呢&#xff1f;因为你看似熟悉的东西&#xff0c;其实对于源码层级了解得少之又少&#xff0c;到头来只有一种陌生的感觉&#xff0c;使用了吗&#xff1f;使用…

技术分享 | 多测试环境的动态伸缩实践

本文将从敏捷研发团队的环境需求与痛点出发&#xff0c;分享如何基于云构建可弹性伸缩的自动化生成式多测试环境&#xff1b;更在经济效益层面&#xff0c;提供了多种成本优化方案&#xff0c;以满足研发团队低成本、高效益的多测试环境运行目标。 一、当前遇到的环境问题 初…