day7 同步互斥

news2025/2/25 12:21:41

作业

1.将一个文件中的数据打印到终端上类似cat一个文件,要求如下

(1)a线程读取文件中的数据
(2)B线程将A线程读取到的数据打印到终端上
(3)文件打印完毕后,结束进程

方法1:用互斥锁和条件变量

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int flag=0;
char c;
struct info{
	int file_r;
	off_t size;
};
void* callback_A(void* arg)//arg=&copy
{

	struct info *info = (struct info *)arg;
	for(int i=0;i<info->size;i++)
	{
		//---------临界区------------
		//上锁
		pthread_mutex_lock(&mutex);
		if(0!=flag)
		{
			pthread_cond_wait(&cond,&mutex);
		}
		read(info->file_r,&c,1);
		flag=1;
		//---------------临界区----------
		pthread_cond_signal(&cond);
		//开锁
		pthread_mutex_unlock(&mutex);
	}
	pthread_exit(NULL);
}
void* callback_B(void* arg)
{
	struct info * info=(struct info *)arg;
	for(int i=0;i<info->size;i++)
	{
		//上锁
		pthread_mutex_lock;
		if(1!=flag)
		{
			//
			pthread_cond_wait(&cond,&mutex);
		}
		//写入终端
//		write(1,&c,1);
		printf("%c", c);
		flag=0;
		pthread_cond_signal(&cond);
		pthread_mutex_unlock(&mutex);
	}
	pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
	//打开文件
	struct info copy;
	copy.file_r = open("./sem.c",O_RDONLY);
	if(copy.file_r<0 )
	{
		perror("open");
		return -1;
	}
	//计算文件大小
	copy.size = lseek(copy.file_r,0,SEEK_END);
	//创建线程
	pthread_t tid1,tid2;
	if(pthread_create(&tid1,NULL,callback_A,&copy)!=0)
	{
		perror("callback_A create failed\n");
		return -1;
	}
	if(pthread_create(&tid2,NULL,callback_B,&copy)!=0)
	{
		perror("callback_B create failed\n");
		return -1;
	}
	//创建一个互斥锁
	if(pthread_mutex_init(&mutex,NULL)!=0)
	{
		perror("pthread_mutex_init error");
		return -1;
	}
	//创建一个条件标量
	if(pthread_cond_init(&cond,NULL)!=0)
	{
		perror("pthread_cond_init error");
		return -1;
	}
	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);
	//销毁互斥所
	pthread_mutex_destroy(&mutex);
	//销毁条件变量
	pthread_cond_destroy(&cond);
	//关闭文件
	close(copy.file_r);
	return 0;
}

方法2:用信号量

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
char c;
sem_t sem1;
sem_t sem2;
struct info{
	int file_r;
	off_t size;
};
void* callback_A(void* arg)//arg=&copy
{

	struct info *info = (struct info *)arg;
	for(int i=0;i<info->size;i++)
	{
		//---------临界区------------
	sem_wait(&sem1);
			read(info->file_r,&c,1);
//			printf("%c",c);
	sem_post(&sem2);
			//---------------临界区----------
	}
	pthread_exit(NULL);
}
void* callback_B(void* arg)
{
	struct info * info=(struct info *)arg;
	for(int i=0;i<info->size;i++)
	{
		//写入终端
	sem_wait(&sem2);
       	write(1,&c,1);
//	    printf("%c",c);
//		fflush(stdout);
	sem_post(&sem1);
//		printf("-----------\n");
	
	}

	pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
	//打开文件
	struct info copy;
	copy.file_r = open("./sem.c",O_RDONLY);
	if(copy.file_r<0 )
	{
		perror("open");
		return -1;
	}
	//计算文件大小
	copy.size = lseek(copy.file_r,0,SEEK_END);
	lseek(copy.file_r,0,SEEK_SET);
	//创建线程
	pthread_t tid1,tid2;
	if(pthread_create(&tid1,NULL,callback_A,&copy)!=0)
	{
		perror("callback_A create failed\n");
		return -1;
	}
	if(pthread_create(&tid2,NULL,callback_B,&copy)!=0)
	{
		perror("callback_B create failed\n");
		return -1;
	}
	//创建信号量
	if(sem_init(&sem1,0,1) != 0)
	{
		perror("sem_init1 error");
		return -1;
	}
	if(sem_init(&sem2,0,0) != 0)
	{
		perror("sem_init2 error");
		return -1;
	}
	//创建互斥
	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);
	//关闭文件
	close(copy.file_r);
	return 0;
}

2、用条件变量实现,有编号为ABC的三个线程,线程内分别打印自己的线程编号,要求打印的顺序为ABC

(1)提示:使用多个条件变量

#include <stdio.h>
#include <pthread.h>
#include <error.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
pthread_cond_t cond3 = PTHREAD_COND_INITIALIZER;

int flag=0;
void* callBack_A(void* arg)
{
	while(1)
	{
		//上锁
		pthread_mutex_lock(&mutex);
		if(flag != 0)
		{
			pthread_cond_wait(&cond1,&mutex);
		}
		printf("A");
		flag=1;
		pthread_cond_signal(&cond2);
		//关锁
		pthread_mutex_unlock(&mutex);
	}
	pthread_exit(NULL);
}
void* callBack_B(void* arg)
{
	while(1)
	{
		//上锁
		pthread_mutex_lock(&mutex);
		if(flag != 1)
		{
			pthread_cond_wait(&cond2,&mutex);
		}
		printf("B");
		flag=2;
		pthread_cond_signal(&cond3);
		pthread_mutex_unlock(&mutex);
	}
	pthread_exit(NULL);
}
void* callBack_C(void* arg)
{
	while(1)
	{
		//上锁
		pthread_mutex_lock(&mutex);
		if(flag != 2)
		{
			pthread_cond_wait(&cond3,&mutex);
		}
		printf("C");
		printf("\n");
		flag=0;
		pthread_cond_signal(&cond1);
		//关锁
		pthread_mutex_unlock(&mutex);
	}
	pthread_exit(NULL);
}

int main(int argc, const char *argv[])
{
	//创建线程
	pthread_t tid1,tid2,tid3;
	if(pthread_create(&tid1,NULL,callBack_A,NULL)!=0)
	{
		perror("callBack_A create error");
		return -1;
	}
	if(pthread_create(&tid2,NULL,callBack_B,NULL)!=0)
	{
		perror("callBack_Bcreate error");
		return -1;
	}

	if(pthread_create(&tid3,NULL,callBack_C,NULL)!=0)
	{
		perror("callBack_C create error");
		return -1;
	}
	//创建一个互斥锁
	if(pthread_mutex_init(&mutex,NULL)!=0)
	{
		perror("mutex init error");
		return -1;
	}
	//创建条件标量
	if(pthread_cond_init(&cond1,NULL)!=0)
	{
		perror("cond1 init error");
		return -1;
	}
    if(pthread_cond_init(&cond2,NULL)!=0)
	{
		perror("cond2 init error");
		return -1;
	}
    if(pthread_cond_init(&cond3,NULL)!=0)
	{
		perror("cond3 init error");
		return -1;
	}

    pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);
	pthread_join(tid3,NULL);
	//销毁互斥锁
	pthread_mutex_destroy(&mutex);
	//销毁条件标量
	pthread_cond_destroy(&cond1);
	pthread_cond_destroy(&cond2);
	pthread_cond_destroy(&cond3);
	return 0;
}

结果:

在这里插入图片描述

3.要求用信号的方式实现,打印一次倒置一次。不允许使用flag,

提示:用多个信号量

#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <semaphore.h>
char buf[]="1234567";
sem_t sem1;
sem_t sem2;
void* callBack_print(void* arg)
{
	while(1)
	{
		sem_wait(&sem1);
		printf("%s\n",buf);
		sem_post(&sem2);
		sem_post(&sem1);
	}
	pthread_exit(NULL);
}
void* callBack_swap(void* arg)
{
	while(1)
	{
		char temp;
		int i=0,j=strlen(buf)-1;
		while(i<j)
		{
			temp=buf[i];
			buf[i]=buf[j];
			buf[j]=temp;
			i++;j--;
		}
//		printf("%s\n",buf);
		sem_post(&sem1);
		sem_wait(&sem2);
	}
	pthread_exit(NULL);

}
int main(int argc, const char *argv[])
{
	sem_init(&sem1,0,1);
	sem_init(&sem2,0,1);
	pthread_t tid1,tid2;
	//创建线程
	if(pthread_create(&tid1,NULL,callBack_print,NULL)!=0)
	{
		fprintf(stderr,"pthread_create error __%d__\n",__LINE__);
		return -1;
	}
    if(pthread_create(&tid2,NULL,callBack_swap,NULL)!=0)
	{
		fprintf(stderr,"pthread_create error __%d__\n",__LINE__);
		return -1;
	}
	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);
	sem_destroy(&sem1);
	sem_destroy(&sem2);
	return 0;
}

结果:
在这里插入图片描述

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

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

相关文章

CMMI流程规范—服务与维护

服务与维护&#xff08;Service and Maintenance, SM&#xff09;是指产品销售之后的客户服务和产品维护。客户服务和产品维护的宗旨就是提高客户对产品以及对开发方的满意度。服务与维护过程域是SPP模型的重要组成部分。本规范阐述了服务与维护过程域的两个主要规程&#xff1…

蓝库云|五大关键引领制造业数字化智慧升级

蓝库云根据《2023制造产业趋势展望》报告&#xff0c;并归纳出「强化企业韧性与敏捷、提升留才诱因、建构多元供应链、兼顾安全的智慧工厂、循环催化永续经营」是牵动制造产业发展的五大关键。将永续目标整合至企业中长期策略中&#xff1b;数字化方面则搭配五大发展关键&#…

【Redis应用】基于Redis实现共享session登录(一)

&#x1f697;Redis应用学习第一站~ &#x1f6a9;本文已收录至专栏&#xff1a;数据库学习之旅 &#x1f44d;希望您能有所收获 &#x1f449;相关推荐&#xff1a;使用短信服务发送手机验证码进行安全校验 一.引入 ​ 在开发项目过程中&#xff0c;我们常常能碰到需要登录注…

Linux操作系统学习(文件IO)

文章目录基础IO系统相关接口文件描述符一切皆文件文件描述符的分配规则重定向fork后的文件描述符基础IO 系统相关接口 在C语言中对文件的操作有fopen打开、fclose关闭、fread读、fwrite写等函数&#xff1b;其实这些都是在系统调用接口上进行的封装。 这里介绍4个系统调用接…

【异常】因多租户字段缺少导致Error updating database. Column ‘tenant_id‘ cannot be null

一、报错内容 org.springframework.dao.DataIntegrityViolationException: ### Error updating database. Cause: java.sql.SQLIntegrityConstraintViolationException: Column tenant_id cannot be null ### The error may exist in com/xxx/cloud/mall/admin/mapper/Goods…

303. 区域和检索 - 数组不可变

303. 区域和检索 - 数组不可变 给定一个整数数组 nums&#xff0c;处理以下类型的多个查询: 计算索引 left 和 right &#xff08;包含 left 和 right&#xff09;之间的 nums 元素的 和 &#xff0c;其中 left < right 实现 NumArray 类&#xff1a; NumArray(int[] num…

英语六级的三大经典句型

目录 1.强调句型&#xff08;提前想好要写在哪个地方&#xff09; 2.虚拟语气 3.第三个句型 3.倒装&#xff08;写一到两个倒装&#xff09; &#xff08;1&#xff09;否定词放在句首就是倒装 &#xff08;2&#xff09;so...that句型结构的句子将so引导的部分置于句首时…

一、一篇文章打好高数基础-函数

1.连续函数的性质考点分析函数的连续性主要考察函数的奇偶性、有界性、单调性、周期性。例题判断函数的奇偶性的有界区间为&#xff08;&#xff09; A.(-1,0) B(0,1) C(1,2) D(2,3)2.闭区间上连续函数的性质考点分析闭区间上连续函数的性质主要考察函数的最大最小值定理、零点…

JavaScript 函数参数

JavaScript 函数对参数的值(arguments)没有进行任何的检查。JavaScript 函数参数与大多数其他语言的函数参数的区别在于&#xff1a;它不会关注有多少个参数被传递&#xff0c;不关注传递的参数的数据类型。函数显式参数与隐藏参数(arguments)在先前的教程中&#xff0c;我们已…

删除启动台(LaunchPad)残留的图标

忘记什么版本的时候以前在 “应用程序” 删除应用后&#xff0c;启动台自动更新删掉 不知道什么时候开始&#xff0c;直接在 “应用程序” 里删掉后&#xff0c;启动台居然不能删除了…… 10.13和10.14后&#xff0c;无论是按住 Option&#xff0c;还是按住 Control Option …

Fisco-Bcos的环境搭建及Data-Export导出组件的使用

注意&#xff1a;由于Data-Export组件暂时只支持Fisco-Bcos 2.x系列&#xff08;这个也是目前使用最多最稳定的系列&#xff09;&#xff0c;故这里使用的是目前最新的Fisco-Bcos 2.x。 Fisco-Bcos链环境搭建 区块链网络部署 主要一步步按照这个官方的操作即可区块链网络搭建…

飞桨paddlespech 语音唤醒初探

PaddleSpeech提供了MDTC模型&#xff08;paper: The NPU System for the 2020 Personalized Voice Trigger Challenge&#xff09;在Hey Snips数据集上的语音唤醒(KWS)的实现。这篇论文是用空洞时间卷积网络&#xff08;dilated temporal convolution network, DTCN&#xff09…

Java 类和对象简介

类是对象的抽象&#xff0c;是一组具有相同特性&#xff08;属性&#xff0c;事物的状态信息&#xff09;和行为&#xff08;事物能做什么&#xff09;的事物的集合&#xff0c;可以看做一类事物的模板。 对象是类的实例化&#xff0c;是具体的事物。 比如&#xff1a;人类和…

linux基本功之列之wget命令实战

文章目录前言一. wget命令介绍二. 语法格式及常用选项三. 参考案例3.1 下载单个文件3.2 使用wget -o 下载文件并改名3.3 -c 参数&#xff0c;下载断开链接时&#xff0c;可以恢复下载3.4 wget后台下载3.5 使用wget下载整个网站四. 补充与汇总常见用法总结前言 大家好&#xff…

C. Good Subarrays(前缀和)

C. Good Subarrays一、问题二、分析三、代码一、问题 二、分析 这道题目的意思就是给我们一个数组&#xff0c;然后我们从数组中选取一个连续的区间&#xff0c;这个区间满足条件&#xff1a;区间内的元素和等于区间的长度。 对于区间和问题我们先想到的是前缀和的算法。 那…

【测绘程序设计】——空间直角坐标转换

测绘工程中经常遇到空间直角坐标转换——比如,北京54(或西安80)空间直角坐标转换成CGCS2000(或WGS-84)空间直角坐标,常用转换模型包括:①布尔沙模型(国家级及省级范围);②莫洛坚斯基模型(省级以下范围);③三维四参数(小于22局部区域) 等。   本文分享了基于布…

Scala变量和数据类型

文章目录Scala变量和数据类型一、注释1. 基本语法2. 案例实操3. 代码规范二、变量和常量&#xff08;重点&#xff09;1. 回顾&#xff1a;Java 变量和常量语法2. 基本语法3. 案例实操三、标识符的命名规范1. 命名规则2. 案例实操四、字符串输出1. 基本语法2. 案例实操五、键盘…

【大数据监控】Grafana、Spark、HDFS、YARN、Hbase指标性能监控安装部署详细文档

目录Grafana简介下载软件包安装部署修改配置文件创建用户创建Systemd服务启动 GrafanaSpark应用监控 Graphite_exporterHDFS 监控YARN 监控HBase 监控Grafana 简介 Grafana 是一款开源的数据可视化工具&#xff0c;使用 Grafana 可以非常轻松的将数据转成图表(如下图)的展现形…

Java实现单向链表

✅作者简介&#xff1a;热爱Java后端开发的一名学习者&#xff0c;大家可以跟我一起讨论各种问题喔。 &#x1f34e;个人主页&#xff1a;Hhzzy99 &#x1f34a;个人信条&#xff1a;坚持就是胜利&#xff01; &#x1f49e;当前专栏&#xff1a;Java数据结构与算法 &#x1f9…

DevOps in China:15年来,DevOps在中国经历了什么?

纵观21世纪软件工程的发展&#xff0c;2009年一定是具有里程碑意义的一年。 自21世纪初&#xff0c;为了使软件快速适应复杂多变的市场环境、满足频繁变化的业务需求&#xff0c;软件开发开始不断应用以Scrum、精益开发、看板、极限编程为代表的敏捷开发方法&#xff0c;但此类…