【Linux】线程(二:线程控制)

本篇文章主要围绕线程控制来进行展开。
主题思路是以create与join两个接口展开。

目录

  • pthread_create 与 pthread_join:
    • pthread_create:
    • pthread_join:
  • 代码:
    • 问题一:主线程与新线程谁先退出?
    • 问题二:哪个线程应该最后退出?
    • 问题三:tid是什么样子的?
    • 问题四:怎么更好的理解新线程函数的传参?
    • 问题五:怎么更好的理解新线程函数的返回值?
    • 问题六:如何创建多线程?
    • 问题七:线程如何终止?
    • 问题九:可以不进行join吗?

pthread_create 与 pthread_join:

现在只是粗略的了解一下create与join这个函数的参数与返回值:

pthread_create:

这是进行线程创建的函数
在这里插入图片描述
参数一:
他是一个输出型参数,为线程的id,这是库提供的类型,本是一个无符号长整型。在这里插入图片描述
参数二:
这个是关于线程属性的,不会用到,我们写为nullptr即可。
参数三:
是一个函数指针,是我们新线程要去执行的函数。
参数四:
传参给参数三中的函数。

关于返回值,带有pthread前缀的函数返回值都是统一的:
成功时返回0,失败时返回错误码。

pthread_join:

我们的进程需要等待,线程当然也需要进行等待,join就是。
在这里插入图片描述
参数一:
将指定tid传给他即可。
参数二:
这是接收新线程执行函数的返回值,我们暂时不关心,先设置为nuliptr。

随后会围绕这两个函数进行展开,细节都会涉及到。

代码:

进程控制本质上就是一堆的函数调用,我们当然是要结合代码来看。

问题一:主线程与新线程谁先退出?

我们先写一段最简单的代码:
在这里插入图片描述
观察现象:
在这里插入图片描述
那么这里后出现一个问题,也就是我们的问题一。
在这里插入图片描述
所以应该谁先运行,答案是不确定的,
因为它取决于OS的调度策略与运气等因素,好吧…

问题二:哪个线程应该最后退出?

与我们的进程一样,进程需要父进程来进行等待,所以父进程应最后退出;
线程也应该是主线程最后退出,进行对应的等待。

那么怎么保证他可以最后退出?答案就是join会进行阻塞等待。

如果主线程不进行join?
当主线程退了,那么整个进程就相当于退出了。我们不推荐这种做法,这样的行为是没有意义的。
当主线程没退,新线程跑完,会出现类似僵尸进程的概念。

对于join可以进行等待我们可以验证一下:

在这里插入图片描述
对threadRun进行修改一下即可。
利用命令:while ;: do ps -aL ; sleep 1; done进行观察,果然过了5s后都退出了。
在这里插入图片描述

问题三:tid是什么样子的?

我们已经说过他的本质是一个无符号数字,我们来看看:
他是什么样子。

在这里插入图片描述
打印出来是个很大的数字?
在这里插入图片描述
为什么和我们的LWP不一样?
tid实际上是一个虚拟地址,更具体一些的需要等等再说。

问题四:怎么更好的理解新线程函数的传参?

我们已经实验过使用对于传参我们可以传一个字符串,进行强转就可以使用,那么我们可以穿内置类型指针,甚至自定义类型指针?

我们一步一步来看,先来看内置类型的。

我们先在栈中定义一个变量a,将他的地址强转为void*传给函数。
在这里插入图片描述

现象:果然循环5次打印10。
在这里插入图片描述
那么自定义类型?

代码:
在这里插入图片描述

在这里插入图片描述
对于ThreadRun函数修改一下打印即可。
在这里插入图片描述
现象:
在这里插入图片描述
这就意味着我们可以给线程传递多个参数甚至是方法。

但是我们这样写的代码还有一个问题,因为我们创建的data对象在主线程栈区中,这样做会有两个后果:

  1. 破坏了主线程的完整性
  2. 若存在多线程,每一个都会这个变量做修改,会影响别的进程。

所以我们推荐在堆上开辟空间。
在这里插入图片描述

问题五:怎么更好的理解新线程函数的返回值?

与我们的问题四一样,也可以传递各种各样的数据地址。

但是我们现在要了解一下join的返回值,因为我们在上边一直说现在我们不关心,设置为nullptr即可。

在这里插入图片描述

在这里插入图片描述
但是为什么传入的是一个void**的二级指针呢?
因为我们想得到返回值是void类型,如果传递给他一个void的值,因为形参是实参的临时拷贝,所以传递void*并不会得到你想要的值,只能传递他的地址。

含义与下段代码的是一致的,如果进行传值返回是得不到对应的期望值的。在这里插入图片描述

我们让新线程函数返回一个整数来感受一下。

局部修改后的代码:返回一个void*
在这里插入图片描述
使用long long接收一下即可,使用int会报err,因为int是4字节,而64
位下地址为8字节。
在这里插入图片描述
现象:果然拿到了111
在这里插入图片描述
其实这个也可以当做退出码来理解。

对于进程来说,一个进程退出有3中状态

  1. 代码跑完,结果不对
  2. 代码跑完,结果对
  3. 出异常。

这个线程的返回值可以做到前两点,那么出异常呢?
线程是进程的一部分,线程收到异常进程就会收到异常,理所当然的进程就结束掉了。

验证:
让新线程出现野指针的错误,同时对主线程休眠100s,观察是否会直接终止。
在这里插入图片描述
现象:

在这里插入图片描述
所以我们也侧面验证了多线程的健壮性比较差。

问题六:如何创建多线程?

因为多个线程创建好创建但是回收有点麻烦,因此我们可以搞一个vector容器将tid进行管理,这样join时也容易join。

非常的简单哦,注意不要讲主线程栈上的地址当做参数传给新线程!
如果在循环中这样做的话会导致两个问题

  1. 对象不断被覆盖(若是编译器优化时不重新分配地址,直接用上一个;若是重新分配则上一个实际上就已经被销毁了,你只是在非法访问!)。
  2. 出了for循环对象销毁。

代码:
在这里插入图片描述
现象:在这里插入图片描述

问题七:线程如何终止?

前六个问题已经将创建与等待部分的内容都涉及了,接下来就是新线程的终止等问题。

方法1: return
我们终止新线程时一直使用的都是此方法,就不在进行赘述了。

那我们可以进行exit吗?
不可以,这个是用来终止进程的!

方法二pthread_exit
虽然不允许exit,但是线程库提供了pthread_exit。
在这里插入图片描述
这个函数使用方法与return完全一致,将其中的参数填为你想return的值即可。

方法三:pthread_cancel
在这里插入图片描述

这个一般用主线程进行取消。

关于取消后的新线程返回值,为-1。

代码:
在这里插入图片描述
dfa87c76139ec6f6c1.png)

现象:
在这里插入图片描述

注意:我们进行取消时一定要保证线程先存在!若是create后直接cancel因为竞态条件等因素的存在可能会导致先cancel再create。

问题九:可以不进行join吗?

不想等待子进程时我们直接对子进程进行捕捉进而忽略即可,那么现成有这种方法吗?

答案是有的!
线程分离。
在这里插入图片描述

a. 一个线程被创建默认是joinable的,必须被join
b. 如果一个线程被分离,那么他的工作状态为分离状态,不需要也不能被join。

我们举一个例子来进行理解:

一个家庭里有一非常叛逆的儿子,与家人争吵了,虽然还在一个屋檐下,但是不管那个孩子了。

分离的线程就是那个儿子,他不需要被等待了,这就叫分离。

我们有两种分离,比如你找你的父亲吵架,或者你的父亲找你吵架,对应着新线程分离与主线程分离。

我们分别来看一看~
新线程主动分离:

我们的线程有一个获取自己LWP的方法:pthread_self,与getpid一样。
在这里插入图片描述
返回值:
在这里插入图片描述

被分离的进程进行join会直接返回,不在阻塞了!

同样,主线程也是同理。

本节完~

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

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

相关文章

【关键点检测和描述】SuperPoint

一、引言 论文: SuperPoint: Self-Supervised Interest Point Detection and Description 作者: Magic Leap 代码: SuperPoint 特点: 提出Homographic Adaptation策略,提升模型从虚拟数据迁移到真实数据的表现&#x…

邻氯苯甲酰氯在医药、农药等领域应用广泛 市场需求稳定且有增长趋势

邻氯苯甲酰氯在医药、农药等领域应用广泛 市场需求稳定且有增长趋势 邻氯苯甲酰氯又称为2-氯苯甲酰氯、氯化邻氯苯甲酰,化学式为C7H4Cl2O,是一种化学物质,外观为黄色液体,不溶于水,溶于醇、醚、丙酮,有强烈…

第100+12步 ChatGPT学习:R实现KNN分类

基于R 4.2.2版本演示 一、写在前面 有不少大佬问做机器学习分类能不能用R语言,不想学Python咯。 答曰:可!用GPT或者Kimi转一下就得了呗。 加上最近也没啥内容写了,就帮各位搬运一下吧。 二、R代码实现KNN分类 (1&a…

API 设计技巧:基础知识与实践的方法

在这篇深入探讨中,我们将从基础开始,逐步介绍 API 设计,并探讨定义卓越API的最佳实践。 作为一名开发者,你可能已经熟悉了许多这些概念,但我将提供详细解释,以加深你的理解。 API 设计:电子商…

图纸管理最佳实践:从混乱到有序的转变

图纸管理最佳实践:从混乱到有序的转变 在工程项目中,图纸是不可或缺的重要资料,它们承载着设计者的智慧与心血。然而,随着项目的推进和时间的推移,图纸管理往往变得混乱不堪,给项目的顺利进行带来诸多不便。…

ROS(四)

write in advance 实验四,在经历了实验三的失败后,卷土重来。 幸运的是,此次实验很简单,很快就能搞定。 Part one 使用指令查看自己摄像头的设备号,如果报错,且你为虚拟机,可能是未在虚拟机处…

Java学习 (二)关键字、标识符、数组

一、关键字 我们第一章案例中有很多关键字,比如class、public、static、void等,这些关键字依旧被java定义好了,可以拿来用,不需要死记硬背,按照官方文档查询即可 #官方文档 https://docs.oracle.com/javase/tutorial/j…

docker-compose设置永久启动、自动重启

步骤一 找到 docker-compose.yml 文件 步骤二 vim 打开文件 找到 image: PS:就是为了对齐格式 步骤三 在其下方添加: restart: always而后保存即可

打开nginx连接的php页面报错502

目录 问题描述: 原因: 1. 使用 Unix 域套接字(Unix Socket) 区别和优势: 2. 使用 TCP/IP 套接字 区别和优势: 如何选择 扩展:Rocky_Linux9.4安装PHP的步骤: 使用Remi存储库…

Wifi通信协议:WEP,WPA,WPA2,WPA3,WPS

前言 无线安全性是保护互联网安全的重要因素。连接到安全性低的无线网络可能会带来安全风险,包括数据泄露、账号被盗以及恶意软件的安装。因此,利用合适的Wi-Fi安全措施是非常重要的,了解WEP、WPA、WPA2和WPA3等各种无线加密标准的区别也是至…

通过防抖动代码解决ResizeObserver loop completed with undelivered notifications.

通过防抖动代码解决ResizeObserver loop completed with undelivered notifications. 一、报错内容二、解决方案解释: 一、报错内容 我通过el-tabs下的el-tab-pane切换到el-table出现的报错,大致是渲染宽度出现了问题 二、解决方案 扩展原生的 Resiz…

Android 应用加固与重签名—使用AndroidStudio自带工具 apksigner

由 AndroidStudio 生成的release版本的app有自己的签名,但当应用加固后会删除原签名,需要重新签名。 一、加固方式: 使用基础版的腾讯云(乐固)进行免费加固,上传软件后等待在线加固完成后下载 apk 即可。…

vue3+ts+vite集成eslint

项目中安装eslint yarn add eslint -Deslint初始化 npx eslint --init按照下方操作即可 安装typescript-eslint/parser yarn add typescript-eslint/parser -D安装vite-plugin-eslint2 yarn add vite-plugin-eslint2 -D配置vite-plugin-eslint2 // vite.config.ts import …

钡铼技术BL104在环境监测站多协议采集保障数据全面准确

随着工业化和城市化进程的加快,环境污染问题日益严重,环境监测站在保护生态环境、保障公众健康中的作用变得越来越重要。钡铼技术PLC物联网关BL104,为环境监测站提供了一种高效、可靠的多协议数据采集解决方案,保障了监测数据的全…

如何实现对文件发送全生命周期的外发管理?

在日常工作中,我们需要经常和企业外部的机构或者个人,发送一些企业内部的文档或者图纸等资料。但企业在文件外发管理上,仍存在一定漏洞,有些员工会通过一些手段,将重要核心文件数据发过去,包括但不仅限于以…

【数据结构(邓俊辉)学习笔记】二叉搜索树02——查找、插入和删除

文章目录 1.概述2. 查找2.1 查找:算法2.2 查找:理解2.3 查找:实现2.4 查找:语义 3. 插入3.1 插入:算法3.2 插入:实现 4. 删除4.1 删除:框架4.2 删除:单分支4.3 删除:双分…

MySQL----redo log重做日志原理及流程

重做日志 redo log:重做日志,用于记录事务操作的变化,确保事务的持久性。redo log是在事务开始后就开始记录,不管事务是否提交都会记录下来,在异常发生时(如数据持久化过程中掉电),…

笔记-python里面的xlrd模块详解

那我就一下面积个问题对xlrd模块进行学习一下: 1.什么是xlrd模块? 2.为什么使用xlrd模块? 3.怎样使用xlrd模块? 1.什么是xlrd模块? ♦python操作excel主要用到xlrd和xlwt这两个库,即xlrd是读excel&…

成都百洲文化传媒有限公司助力商家扬帆远航

在数字经济的浪潮中,电商行业如日中天,成都百洲文化传媒有限公司正是这一领域的佼佼者。作为一家专注于电商服务的传媒公司,百洲文化以其专业的服务、创新的理念和卓越的成果,在业内树立了良好的口碑,成为众多商家信赖…

大数据实训室建设可行性报告

一、建设大数据实训室的背景与意义 随着信息技术的飞速发展,大数据已成为推动社会进步和经济发展的重要力量。中高职院校作为技能型人才培养的摇篮,承担着为社会输送大数据领域高素质、高技能人才的重要任务。因此,建设大数据实训室&#xf…