线程分离属性、线程互斥、死锁、信号量——进程与线程——day11

今天主要学习了线程分离属性、线程互斥、死锁、信号量

线程分离属性:主要是让线程结束后,自动回收线程空间

pthread_attr_init
    int pthread_attr_init(pthread_attr_t *attr);
    功能:
      	线程属性初始化

pthread_attr_destroy
	int pthread_attr_destroy(pthread_attr_t *attr);
	功能:
 	 	 线程属性销毁

pthread_attr_setdetachstate 
	int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
	功能:
  		设置分离属性 
  		PTHREAD_CREATE_DETACHED   分离属性
  		PTHREAD_CREATE_JOINABLE   加入属性(默认)

练习:练习:定义一个学生结构体
struct student
{
char name[32];
char sex;
int age;
int score;
};
创建两个线程,线程1负责从终端接收学生信息,线程2负责将学生信息打印在终端

#include"head.h"	//头文件

struct student{			//学生结构体
	char name[20];
	char sex;
	int age;
	int score;
};

void *thread1(void *arg)	//线程1:接收信息
{	
	struct student *stu = arg;

	fgets(stu->name,sizeof(stu->name),stdin);
	stu->sex = getchar();
	scanf("%d",&stu->age);
	scanf("%d",&stu->score);

	return NULL;
}

void *thread2(void *arg)	//输出
{
	sleep(10);
	struct student *stu = arg;

	printf("name:%s",stu->name);
	printf("sex:%c\n",stu->sex);
	printf("age:%d\n",stu->age);
	printf("score:%d\n",stu->score);

	return NULL;
}

int main(void)
{
	pthread_t tid1;		//线程1ID
	pthread_t tid2;		//线程2ID
	struct student s; 

	pthread_create(&tid1,NULL,thread1,&s);	//创建线程1
	pthread_create(&tid2,NULL,thread2,&s);	//创建线程2
	
	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);
	
	return 0;
}

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

线程互斥

1.互斥锁:防止资源竞争

2.函数接口:

pthread_mutex_init:
      int pthread_mutex_init(pthread_mutex_t *restrict mutex,
           const pthread_mutexattr_t *restrict attr);
      功能:
        互斥锁初始化
      参数:
        mutex:互斥锁空间首地址
        attr:互斥锁的属性(默认为NULL)
      返回值:
        成功返回0 
        失败返回错误码 

pthread_mutex_destroy:
      int pthread_mutex_destroy(pthread_mutex_t *mutex);
      功能:
        互斥锁销毁
      参数:
        mutex:互斥锁空间首地址
      返回值:
        成功返回0 
        失败返回错误码 

pthread_mutex_lock:
      int pthread_mutex_lock(pthread_mutex_t *mutex);
      功能:
        上锁

pthread_mutex_unlock:
      int pthread_mutex_unlock(pthread_mutex_t *mutex);
      功能: 
        解锁

eg:

#include"head.h"

int val = 0;
int num1 = 0;
int num2 = 0;
pthread_mutex_t lock;	//创建互斥锁

void *thread1(void *arg)	//线程1:两个数自增
{
	while(1)
	{
		pthread_mutex_lock(&lock);	//上锁
		num1 = val;
		num2 = val;
		pthread_mutex_unlock(&lock);	//解锁
		val++;
	}

	return NULL;
}

void *thread2(void *arg)	//线程2:输出全局变量num1,num2
{
	while(1)
	{
		pthread_mutex_lock(&lock);
		if(num1 != num2)
		{
			printf("num1 = %d,num2 = %d\n",num1,num2);
		}
		pthread_mutex_unlock(&lock);
	}
	return NULL;
}

int main(void)
{
	pthread_t tid1;
	pthread_t tid2;
	pthread_mutex_init(&lock,NULL);	//互斥锁初始化

	pthread_create(&tid1,NULL,thread1,NULL);	//创建线程1
	pthread_create(&tid2,NULL,thread2,NULL);	//创建线程2

	pthread_join(tid1,NULL);	//回收线程空间,具有阻塞功能
	pthread_join(tid2,NULL);

	pthread_mutex_destroy(&lock);	//互斥锁销毁

	return 0;
}

结果:
在这里插入图片描述
因为线程与进程一样,宏观并行,微观串行,当无互斥锁时,当线程1进行到给num2赋值时,线程2进行比较并输入,则回输出出来,所以该练习可以体现互斥锁的重要性。

3.临界资源、临界区:

	加锁解锁中间的代码称为临界资源、临界区
    同一时刻临界资源不能同时执行,只能执行其中一个临界资源代码

原子操作:

    CPU最小的一次不能被任务调度打断的操作称为原子操作

互斥锁只能解决资源竞争的问题,无法同步代码(没有先后执行的顺序关系)

死锁

多线程操作互斥锁,导致多个线程均无法向下执行的状态称为死锁状态简称为死锁

	死锁产生的四个必要条件:
 		1.互斥条件
  		2.不可剥夺条件
	  	3.请求保持
  		4.循环等待

	避免产生死锁:
 		1.pthread_mutex_trylock 替代 pthread_mutex_lock
	    2.加锁顺序保持一致

信号量

信号量是一种资源,可以被初始化、申请、释放、销毁
	P操作:申请资源
	V操作:释放资源
sem_init  
    int sem_init(sem_t *sem, int pshared, unsigned int value);
    功能:
      初始化信号量
    参数:
      sem:信号量空间首地址
      pshared:
        0 一个进程中的所有线程间共享
        非0 进程间共享 
      value:
        初始化的值
    返回值:
      成功返回0 
      失败返回-1 
    
    sem_destroy:
    int sem_destroy(sem_t *sem);
    功能:
      信号量的销毁
    参数:
      sem:信号量空间首地址
    返回值:
      成功返回0 
      失败返回-1 

    sem_wait:
    int sem_wait(sem_t *sem);
    功能:
      申请信号量

    sem_post:
    int sem_post(sem_t *sem);
    功能:
      释放信号量

eg:线程1获取字符串,线程2输出

#include"head.h"

char tmpbuff[4096] = {0};
sem_t sem_w;	//定义全局变量信号量
sem_t sem_r;

void *pthread1(void *arg)	//线程1:获取字符串
{
	while(1)
	{	
		sem_wait(&sem_w);	//申请w信号量,信号量-1
		gets(tmpbuff);
		sem_post(&sem_r);	//释放r信号量,信号量+1
	}
	return NULL;
}

void *pthread2(void *arg)	//线程2:输出字符串
{
	while(1)
	{	
		sem_wait(&sem_r);	//申请r信号量,信号量-1
		printf("tmpbuff = %s\n",tmpbuff);
		sem_post(&sem_w);	//释放w信号量,信号量+1
	}
	return NULL;
}

int main(void)
{
	pthread_t tid1;	//线程1ID
	pthread_t tid2;	//线程2ID

	sem_init(&sem_w,0,1);	//w信号量初始化,参数2中0代表一个进程中的所有线程间共享
	//参数3中1代表:初始化的值为1,因为要先进行线程1,需要申请w信号量
	sem_init(&sem_r,0,0);

	pthread_create(&tid1,NULL,pthread1,NULL);	//创建线程1
	pthread_create(&tid2,NULL,pthread2,NULL);	//创建线程2

	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);

	sem_destroy(&sem_w);	//信号量w销毁
	sem_destroy(&sem_r);	//信号量r销毁

	return 0;
}

以上就是今天的全部内容!努力努力!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

k8s(5)

目录 使用Kubeadm安装k8s集群: 初始化操作: 每台主从节点: 升级内核: 所有节点安装docker : 所有节点安装kubeadm,kubelet和kubectl: 修改了 kubeadm-config.yaml,将其传输给…

Redis 16种妙用

1、缓存 2、数据共享分布式 3、分布式锁 4、全局ID 5、计数器 6、限流 7、位统计 8、购物车 9、用户消息时间线timeline 10、消息队列 11、抽奖 12、点赞、签到、打卡 13、商品标签 14、商品筛选 15、用户关注、推荐模型 16、排行榜 1、缓存 String类型 例如:热点…

Magento2常见表的作用

1.sales_sequence_profile 更改订单号或者发票号的前缀及最大值

猫头虎分享已解决Bug || 网络连接问题:NetworkError: Failed to fetch

博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝典!《IDEA开发秘籍》 — 提升你的IDEA技能!《100天精通鸿蒙》 …

手机打开 第三方 “微信、快手、QQ、电话、信息” 等

前期回顾 Vue3 TS Element-Plus —— 项目系统中封装表格搜索表单 十分钟写五个UI不在是问题_vue3 封装table 配置表格-CSDN博客https://blog.csdn.net/m0_57904695/article/details/135538630?spm1001.2014.3001.5501 目录 🤖 下载App如下图所示:…

pytorch --反向传播和优化器

1. 反向传播 计算当前张量的梯度 Tensor.backward(gradientNone, retain_graphNone, create_graphFalse, inputsNone)计算当前张量相对于图中叶子节点的梯度。 使用反向传播,每个节点的梯度,根据梯度进行参数优化,最后使得损失最小化 代码…

IDEA的LeetCode插件的设置

一、下载插件 选择点击File->Setting->Plugins:搜索LeetCode 二、打开这个插件 选择View —>Tool Windows—>leetcode 三、登陆自己的账号 关于下面几个参数的定义,官方给的是: Custom code template: 开启使用自定义模板&…

搜维尔科技:OptiTrack 提供了性能最佳的动作捕捉平台

OptiTrack 动画 我们的 Prime 系列相机和 Motive 软件相结合,产生了世界上最大的捕获量、最精确的 3D 数据和有史以来最高的相机数量。OptiTrack 提供了性能最佳的动作捕捉平台,具有易于使用的制作工作流程以及运行世界上最大舞台所需的深度。 无与伦比…

【k8s配置与存储--持久化存储(PV、PVC、存储类)】

1、PV与PVC 介绍 持久卷(PersistentVolume,PV) 是集群中的一块存储,可以由管理员事先制备, 或者使用存储类(Storage Class)来动态制备。 持久卷是集群资源,就像节点也是集群资源一样…

SpringCloud微服务-Eureka注册中心

Eureka注册中心 文章目录 Eureka注册中心前言1、Eureka的作用2、搭建EurekaServer3、服务注册4、启动多个实例5、服务拉取 -实现负载均衡 前言 在服务调用时产生的问题: //2. 利用RestTemplate发起HTTP请求,查询user String url "http://localho…

【Unity自制手册】Unity—Camera相机跟随的方法大全

👨‍💻个人主页:元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏:Uni…

小甲鱼Python06 序列字典集合

一、序列 1.id函数 is运算符 我们首先思考下字符串、元组、列表的共同点: 都有很多共同的运算符。都可以通过索引来获取元素,第一个元素索引都是0,都可以通过切片的方法获取某个范围内元素的集合。 以上三种统称为序列。序列分为可变序列…

安装极狐GitLab Runner并测试使用

本文继【新版极狐安装配置详细版】之后继续 1. 添加官方极狐GitLab 仓库: 对于 RHEL/CentOS/Fedora: curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh" | sudo bash2. 安装最新版本的极狐G…

多进程服务端进程框架

对父进程来说,不需要客户端连接的socket,对子进程来说,不需要监听的socket。代码中标出了两行关闭对应socket的函数 上图可见,对应的关闭了以后(3是服务端监听的socket,4是客户端连上来的socket) 通过上图…

【GPTs分享】每日GPTs分享之Image Generator Tool

今日GPTs分享:Image Generator Tool。Image Generator Tool是一种基于人工智能的创意辅助工具,专门设计用于根据文字描述生成图像。这款工具结合了专业性与友好性,鼓励用户发挥创造力,同时提供高效且富有成效的交互体验。 主要功能…

10:00面试,10:05就出来了,问的问题过于变态了。。。

我从一家小公司转投到另一家公司,期待着新的工作环境和机会。然而,新公司的加班文化让我有些始料未及。虽然薪资相对较高,但长时间的工作和缺乏休息使我身心俱疲。 就在我逐渐适应这种高强度的工作节奏时,公司突然宣布了一则令人…

C++ Webserver从零开始:代码书写(十四)——http连接处理

前言 HTTP类是Webserver到目前为止最为庞大的类。其实最开始我是只想分析它的部分代码,但是最后我还咬咬牙将http连接处理的全代码分析写完了。因此,本文会特别的长,我相信没人可以把它一口气全部读完。不过我在本文中进行了细致的目录划分&a…

部署roop实现视频人脸替换

roop只需要一张人脸的图像,就可以替换视频中的脸。不需要数据集和模型训练。 下载对应版本的cudnn https://developer.nvidia.com/rdp/cudnn-archivehttps://developer.nvidia.com/rdp/cudnn-archive解压后的三个文件夹拷贝到cuda的目录 C:\Program Files\NVIDIA…

【非递归版】归并排序算法(2)

目录 MergeSortNonR归并排序 非递归&归并排序VS快速排序 整体思想 图解分析​ 代码实现 时间复杂度 归并排序在硬盘上的应用(外排序) MergeSortNonR归并排序 前面的快速排序的非递归实现,我们借助栈实现。这里我们能否也借助栈去…

uniapp实现单选框

采用uniapp-vue3实现的一款单选框组件,提供丝滑的动画选中效果,支持不同主题配置,适配web、H5、微信小程序(其他平台小程序未测试过,可自行尝试) 可到插件市场下载尝试: https://ext.dcloud.net…
最新文章