【0804作业】顺序执行2个线程 (完成逆置打印、拷贝文件) (实现类似cat打印到终端)

news2025/1/16 18:06:47

作业1: 要求定义一个全局变量 char buf[] = "1234567",创建两个线程,不考虑退出条件

   要求定义一个全局变量 char buf[] = "1234567",创建两个线程,不考虑退出条件,另:

  1. A线程循环打印buf字符串,
  2. B线程循环倒置buf字符串,即buf中本来存储1234567,倒置后buf中存储7654321. 不打印!!
  3. 倒置不允许使用辅助数组。
  4. 要求A线程打印出来的结果只能为 1234567 或者 7654321 不允许出现7634521 7234567
  5. 不允许使用sleep函数
  6. 要求打印,倒置线程,顺序执行。运行顺序为:线程1 线程2 线程1 线程2 ...,出现的现象为先打印1234567,再打印7654321...
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

//2.在第一题的基础。上加上一一个需求:要求打印,倒置线程,顺序执行。出现的现象为先打印1234567,后打印7654321

char buf[]="1234567";

//定义两个信号量
sem_t sem1,sem2;

void* callback_1(void* arg)//打印
{
	while(1)
	{
		//P操作
		if(sem_wait(&sem1)<0)
		{
			perror("sem_wait");
			return NULL;
		}
		printf("%s\n",buf);
		//V操作
		if(sem_post(&sem2) < 0)
		{
			perror("sem_post");
			return NULL;
		}
	}
}

void* callback_2(void* arg)//逆置 不打印
{
	char t=0;
	while(1)
	{
		//P操作
		if(sem_wait(&sem2)<0)
		{
			perror("sem_wait");
			return NULL;
		}
		for(int i=0;i<strlen(buf)/2;i++)
		{
			t=buf[i];
			buf[i] = buf[strlen(buf)-1-i];
			buf[strlen(buf)-1-i] = t;
		}
		//V操作
		if(sem_post(&sem1) < 0)
		{
			perror("sem_post");
			return NULL;
		}
	}
	pthread_exit(NULL);
}

int main(int argc, const char *argv[])
{
	if(sem_init(&sem1, 0, 1)<0)
	{
		perror("sem_init");
		return -1;
	}
	printf("sem_init success __%d__\n",__LINE__);

	if(sem_init(&sem2, 0, 0)<0)
	{
		perror("sem_init");
		return -1;
	}
	printf("sem_init success __%d__\n",__LINE__);
	
	//创建2个线程
	pthread_t tid_1,tid_2;
	if(pthread_create(&tid_1,NULL,callback_1,NULL)!=0)
	{
		fprintf(stderr,"pthread_create failed __%d__\n",__LINE__);
		return -1;
	}
	pthread_detach(tid_1);  //分离线程1
	if(pthread_create(&tid_2,NULL,callback_2,NULL)!=0)
	{
		fprintf(stderr,"pthread_create failed __%d__\n",__LINE__);
		return -1;
	}

	pthread_join(tid_2,NULL);	//等待阻塞线程2
	
	sem_destroy(&sem1);   //销毁信号量
	sem_destroy(&sem2);   //销毁信号量
	return 0;
}

作业2:创建两个线程,其中一个线程读取文件中的数据,另外一个线程将读取到的内容打印到终端上,类似实现cat一个文件

  1. 创建两个线程
  2. 其中一个线程读取文件中的数据,另外一个线程将读取到的内容打印到终端上,类似实现cat一个文件。
  3. cat数据完毕后,结束两个线程。
  • 提示:先读数据,读到数据后将数据打印到终端上
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <head.h>
#include <fcntl.h>

int fd;
char c;
int res=-1;
sem_t sem1,sem2;

void* callback1(void* arg)
{
	while(1)
	{
		if(sem_wait(&sem1) < 0)
		{
			perror("sem_wait");
			break;
		}
		if(read(fd,&c,1)==0)
		{
			res=close(fd);
			sem_post(&sem1);
			break;
		}
		if(sem_post(&sem2) < 0)
		{
			perror("sem_post");
			break;
		}
	}
	pthread_exit(NULL);
}

void* callback2(void* arg)
{
	while(1)
	{
		if(sem_wait(&sem2) < 0)
		{
			perror("sem_wait");
			break;
		}
		if(0 == res)
			break;
		write(1,&c,1);
		if(sem_post(&sem1) < 0)
		{
			perror("sem_post");
			break;
		}
	}
}


int main(int argc, const char *argv[])
{
	//创建两个线程,其中一个线程读取文件中的数据,另外一个线程将读取到的内容打印到终端上,类似实现cat一个文件。
	//cat数据完毕后,要结束两个线程。
	//提示:先读数据,读到数据后将数据打印到终端上。
	
	//创建信号量
	if(sem_init(&sem1, 0 ,1)<0)
	{
		perror("sem_init");
		return -1;
	}
	if(sem_init(&sem2, 0 ,0)<0)
	{
		perror("sem_init");
		return -1;
	}
	//以读的方式打开文件
	fd=open("./01_pthread_create.c",O_RDONLY);
	if(fd < 0)
	{
		ERR_MSG("open");
		return -1;
	}

	//创建两个线程
	pthread_t tid1,tid2;
	if(pthread_create(&tid1,NULL,callback1,NULL) != 0)
	{
		fprintf(stderr,"pthread_create faile __%d__\n",__LINE__);
		return -1;
	}
	if(pthread_create(&tid2,NULL,callback2,NULL) != 0)
	{
		fprintf(stderr,"pthread_create faile __%d__\n",__LINE__);
		return -1;
	}

	pthread_join(tid1,NULL);//阻塞等待线程1
	pthread_join(tid2,NULL);//阻塞等待线程2

	//销毁信号量
	sem_destroy(&sem1);
	sem_destroy(&sem2);

	return 0;
}

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

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

相关文章

前端食堂技术周刊第 93 期:7 月登陆 Web 平台的新功能、Node.js 工具箱、Nuxt3 开发技巧、MF 重构方案

美味值&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f; 口味&#xff1a;橙橙冰萃美式 食堂技术周刊仓库地址&#xff1a;https://github.com/Geekhyt/weekly 大家好&#xff0c;我是童欧巴。欢迎来到前端食堂技术周刊&#xff0c;我们先来…

第二天 什么是JWT ?

✅作者简介&#xff1a;大家好&#xff0c;我是Cisyam&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Cisyam-Shark的博客 &#x1f49e;当前专栏&#xff1a; 每天一个知识点 ✨特色专…

RocketMQ 主备自动切换模式部署

目录 主备自动切换模式部署 Controller 部署​ Controller 嵌入 NameServer 部署​ Controller 独立部署​ Broker 部署​ 兼容性​ 升级注意事项​ 主备自动切换模式部署 该文档主要介绍如何部署支持自动主从切换的 RocketMQ 集群&#xff0c;其架构如上图所示&#xff…

c++实现Qt信号和槽机制

文章目录 简介信号槽信号与槽的连接 特点观察者模式定义观察者模式结构图 实现简单的信号和槽 简介 信号槽机制与Windows下消息机制类似&#xff0c;消息机制是基于回调函数&#xff0c;Qt中用信号与槽来代替函数指针&#xff0c;使程序更安全简洁。  信号和槽机制是 Qt 的核心…

Scratch 之 大地图引擎怎么做?

引子 简单的介绍一下&#xff0c;一些游戏引擎是有一个隐形小地图存在的&#xff0c;这个隐形小地图通常用来侦测碰碰撞和移动。那么&#xff0c;一个大地图引擎的背景肯定是很大的(一般来说大小都超过200)&#xff0c;如果我们要做出一个枪战作品&#xff0c;那就迟早会发现一…

Spring源码解析(七):bean后置处理器AutowiredAnnotationBeanPostProcessor

Spring源码系列文章 Spring源码解析(一)&#xff1a;环境搭建 Spring源码解析(二)&#xff1a;bean容器的创建、默认后置处理器、扫描包路径bean Spring源码解析(三)&#xff1a;bean容器的刷新 Spring源码解析(四)&#xff1a;单例bean的创建流程 Spring源码解析(五)&…

IBM HR Analytics 员工流失 EDA 和可视化绩效分析

IBM HR Analytics 员工流失与绩效分析 背景导入库输出前五行数据清洗检查空值删除不必要的列 可视化商务旅行直方图离家的距离箱形图教育与数字公司的关系年龄和月收入散点图按教育领域和工作角色划分的工作满意度相关矩阵的交互式热图 背景 揭示导致员工流失的因素&#xff0…

陪诊小程序开发|陪诊系统定制|数字化医疗改善就医条件

健康问题这几年成为人们关注的焦点之一&#xff0c;然而看病却是一个非常麻烦的过程&#xff0c;特别是对于那些身处陌生城市或者不熟悉就医流程的人来说。幸运的是现在有了陪诊小程序下&#xff0c;为您提供便捷的助医服务&#xff0c;使得就医过程得更加简单和轻松。 陪诊系统…

国联易安网页防篡改保护系统“渠道招募”启动啦!

作为业内专注于保密与非密领域的分级保护、等级保护、业务连续性安全和大数据安全的领军企业&#xff0c;国联易安网页防篡改保护系统基于“高效同步”、“安全传输”两项技术&#xff0c;具备了独特的“五重防护”新特性&#xff0c;支持网页的全自动发布、网页监控、报警和自…

webpack基础知识十:与webpack类似的工具还有哪些?区别?

一、模块化工具 模块化是一种处理复杂系统分解为更好的可管理模块的方式 可以用来分割&#xff0c;组织和打包应用。每个模块完成一个特定的子功能&#xff0c;所有的模块按某种方法组装起来&#xff0c;成为一个整体(bundle) 在前端领域中&#xff0c;并非只有webpack这一款…

c51单片机16个按键密码锁源代码(富proteus电路图)

注意了&#xff1a;这个代码你是没法直接运行的&#xff0c;但是如果你看得懂&#xff0c;随便改一改不超过1分钟就可以用 #include "reg51.h" #include "myheader.h" void displayNumber(unsigned char num) {if(num1){P10XFF;P10P11P14P15P160;}else if…

js修改img的src属性显示变换图片到前端页面,img的src属性显示java后台读取返回的本地图片

文章目录 前言一、HTML 图像- 图像标签&#xff08; <img>&#xff09;1.1图像标签的源属性&#xff08;Src&#xff09;1.2图像标签源属性&#xff08;Src&#xff09;显示项目中图片1.3图像标签源属性&#xff08;Src&#xff09;显示网络图片 二、图像标签&#xff08…

韦东山Linux驱动入门实验班(6)LED驱动---设备树

前言 &#xff08;1&#xff09;在韦东山Linux驱动入门实验班&#xff08;5&#xff09;LED驱动—驱动分层和分离&#xff0c;平台总线模型我们已经讲解了如何将驱动程序和硬件程序进行剥离。但是大佬们感觉这样还不行&#xff0c;他们认为要专门弄一个结构存储硬件信息&#x…

树,森林的遍历,以及其与二叉树遍历之间的关系

树和森林的的遍历 树的遍历 先根遍历 以下列树为演示 首先将树转化成二叉树&#xff08;孩子兄弟表示法&#xff1a;就是每个节点的左边连着它的左孩子&#xff0c;右边连自己右边的第一个兄弟&#xff09; 然后把转化为的二叉树进行先序遍历&#xff0c;中序遍历 进行先序…

【c语言初级】c++基础

文章目录 1. C关键字2. 命名空间2.1 命名空间定义2.2 命名空间使用 3. C输入&输出4. 缺省参数4.1 缺省参数概念4.2 缺省参数分类 5. 函数重载5.2 C函数重载的原理--名字修饰采用C语言编译器编译后结果 1. C关键字 C是在C的基础之上&#xff0c;容纳进去了面向对象编程思想…

Spring Cloud Alibaba官方网站

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 官方网站 SCA&#xff08;Spring Cloud Alibaba&#xff09;为分布式应用开发提供一站式解决方案。它包含开发分布式应用程序所需的所有核心组件&#xff0c;使您可以轻松地…

LeetCode 周赛上分之旅 #38 结合排序不等式的动态规划

⭐️ 本文已收录到 AndroidFamily&#xff0c;技术和职场问题&#xff0c;请关注公众号 [彭旭锐] 和 BaguTree Pro 知识星球提问。 学习数据结构与算法的关键在于掌握问题背后的算法思维框架&#xff0c;你的思考越抽象&#xff0c;它能覆盖的问题域就越广&#xff0c;理解难度…

思维能力的学习

前言 在工作中&#xff0c;随着工作时间的增长&#xff0c;我们与他人的差异不是知识本身的差异&#xff0c;主要是思维方面的差异&#xff0c;所以我们需要培养自己的思维能力。 思维能力的学习 思维是一个具备内在框架和逻辑的系统工程&#xff0c;思维覆盖了学习、认知、问…

43..利用fsolve函数解对应lambda下的方程组(matlab程序)

1.简述 fsolve的基本用法 : x fsolve(fun,x0) 其中fun应为函数句柄&#xff0c;x0为搜索的种子&#xff0c;即预估的fun0的解的大致位置。 函数句柄的定义方式主要有两种&#xff1a; 1.定义函数文件&#xff0c;使用操作符 定义function文件root2d.m, 如下&#xff1a; …