Linux应用学习——多线程

news2025/7/8 0:17:59

多线程

在这里插入图片描述

PART1——线程相关概念

​ 线程时参与系统调度的最小单位。被包含在进程之中,是进程中的实际运行单位。一个进程可以创建多个线程,多个线程实现并发运行,每个线程执行不同的任务。

  • 线程时最基本的运行单位,而进程不能运行,真正运行的是进程中的线程
  • 可以认为进程是一个容器,包含了线程运行所需的数据结构、环境变量
  • 其他线程都是由主线程创建
  • 主线程通常会在最后结束运行,执行各种清理工作
  • 同一个进程中的多个线程将共享进程中的全部系统资源,如虚拟地址空间、文件描述符和信号处理等
  • 同一个进程的多个线程之间可以并发执行

1.1 进程与线程

  • 进程间切换开销大
  • 进程间通信麻烦
  • 进程创建速度比线程慢
  • 线程编程难度高

1.2 并行与并发

  • 串行
  • 并行
  • 并发

1.3 线程ID

  • 每个线程都有其对应的标识

  • 线程ID只有在它所属的进程上下文才有意义

  • 通过pthread_t pthread_self(void)获取自己的线程ID

  • 通过int pthread_equal(pthread_t t1,pthread_t t2)检查两个线程ID是否相等

PART2——线程使用

2.1 创建线程

  • 应用程序可以通过int pthread_creat(pthread_t *thread,const pthread_attr_t *attr,void *(*start_routine)(void *),void *arg)来创建一个线程

    • 新创建的线程的线程ID会保存在参数thread所指向的内存中

    • 线程的属性

    • 新创建的线程从start_routine函数开始运行

    • 传递给送start_routine函数的参数

    • 创建成功是返回0

  • 应用程序中使用pthread_creat创建线程后,编译是要指定-lpthread

2.2 终止线程

  • 线程的start_routine函数执行return语句并返回指定值,返回值就是线程的退出码

  • 线程调用void pthread_exit(void *retval)函数来终止调用它的线程

  • 调用pthread_cancel()取消线程

2.3 回收线程

  • 应用程序通过调用int pthread_join(pthread_t thread,void **retval)函数来阻塞等待线程的终止

    • thread等待指定线程终止

    • **retval如果被pthread_exit()终止,则将其退出状态赋值给retval,如果被pthread_cancel()终止,则将PTHREAD_CANCELED放在retval中

  • 线程之间可以互相进行pthread_join(),线程之间是对等的

  • 不能以非阻塞的方式调用pthread_join()

  • 可以通过int pthread_detach(pthread_t thread)将指定线程进程分离,此时线程终止时系统就能够自动回收线程资源并将其移除

    • 设置为分离线程后,便不能在恢复到之前的状态,此过程不可逆

    • 设置为分离线程后,便不能在用pthread_join()回收资源,会出错

  • 可以通过

    void pthread_cleanup_push(void(*routine)(void *),void *arg)

    void pthread_cleanup_pop(int execute)

    分别添加线程清理函数和移除线程的清理函数,成对出现

    • 当线程调用pthread_exit()退出时,添加的清理函数才会被执行

    • 线程响应pthread_cancel()时,添加的清理函数才会被执行

    • 用非零参数调用pthread_cleanup_pop()时,添加的清理函数才会被执行,参数为0时,清理函数不会执行,只会将最顶层的函数移除

2.4 取消线程

  • 通过int pthread_cancel(pthread_t thread)要求一个线程立即终止/退出

  • pthread_cancel()调用后,不会等待目标线程的退出,直接返回

  • 通过int pthread_setcancelstate(int state,int *olestate)设置线程取消的状态

    • state可以设置为:

      • PTHREAD_CANCEL_ENABLE线程可以被取消,默认值

      • PTHREAD_CANCEL_DISABLE线程不可被取消,会将请求挂起,直到取消状态变为PTHREAD_CANCEL_ENABLE

    • olestate,将线程之前的状态保存在此,如果不关心返回状态则可以设置为NULL

  • 通过int pthread_setcanceltype(int type,int *oldtype)设置线程取消的类型

    • type可以设置为:

      • PTHREAD_CANCEL_DEFERRED当取消请求到来时,线程继续运行,直到运行到某个取消点,默认值

      • PTHREAD_CANCEL_ASYNCHRONOUS可能在任何时间点取消线程

  • 可以通过man 7 pthreads查看可以作为取消点的函数

  • 可以通过void pthread_testcancel(void)作为取消点

2.5 线程属性

2.5.1 使用

  • 如果使用默认属性则把pthread_attr_t *attr设置为NULL即可

  • 如果要设置线程属性需要通过int pthread_attr_init(pthread_attr_t *attr)对属性对象进行初始化操作,并在不需要时通过int pthread_attr_destory(pthread_attr_t *attr对属性对象进行销毁

2.5.2 线程栈属性

  • 通过int pthread_attr_setstack(pthread_attr_t *attr,void *stackaddr,size_t stacksize)对栈的起始地址和栈大小进行设置

  • 通过int pthread_attr_getstack(const pthread_attr_t *attr,void **stackaddr,size_t *stacksize)获取栈信息

  • 获取栈代大小pthread_attr_getstacksize()

  • 设置栈大小pthread_attr_gsetstacksize()

  • 获取栈地址pthread_attr_getstackaddr()

  • 设置栈地址pthread_attr_setstackaddr()

2.5.3 分离状态属性

  • 设置分离属性

    int pthread_attr_setdetachstate(pthread_attr_t *attr,int detachstate)

  • 获取分离属性

    int pthread_attr_getdetachstate(const pthread_attr_t *attr,int *detachstate)

  • detachstate的值可以为:

    • PTHREAD_CREATE_DETACHED新建线程直接处于分离属性,系统自动回收资源

    • PTHREAD_CREATE_JOINABLE默认值,正常启动,可以被其他线程获取终止状态信息

2.6 线程安全

2.6.1 可重入函数

  • 如果一个函数被同一个进程的多个不同的执行流同时调用,诶此函数调用总是能产生正确的结果,这样的函数就是可重入函数

  • 可重入函数分为:

    • 绝对的可重入函数(函数内部仅仅操作函数内部定义的局部变量,除了使用栈上的变量以外不依赖任何环境变量,多个副本同时运行时,使用的分离的栈)

    • 带条件的可重入函数

  • 使用man 3 ctime查询时,MT-Safe指的是多线程安全,MT-Unsafe指的是线程不安全

2.6.2 线程安全函数

  • 一个函数被多个线程同时调用时,总会一直产生正确的结果,这样的函数被称为线程安全函数

  • 可重入函数一定是线程安全函数,线程安全函数不一定是可重入函数

  • 可以通过man 7 pthreads查询线程安全函数

2.6.3 一次性初始化

  • 应用程序如果需要只运行一次的函数,则可以通过

    int pthread_once(pthread_once_t *once_control,void(*init_routine)(void))使init_routine函数只运行一次

    通常pthread_once_t once_control = PTHREAD_ONCE_INIT;

  • 具体在哪个线程中执行是不确定的,有内核调度决定

2.6.4 线程特有数据

  • 为每一个调用线程分配属于该线程的私有数据区,为每一个调用线程分别维护一份变量的副本

  • 针对一些非线程安全的函数,使用线程特有数据将其变成线程安全函数

2.6.5 线程局部存储

PART3——线程同步

3.1 互斥锁

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

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

相关文章

顺序表——“数据结构与算法”

各位CSDN的uu们你们好呀,今天小雅兰的内容是数据结构与算法里面的顺序表啦,在我看来,数据结构总体上是一个抽象的东西,关键还是要多写代码,下面,就让我们进入顺序表的世界吧 线性表 顺序表 线性表 线性表&…

为什么要用VR全景?5个答案告诉你

看中了刚上市的一款新车,再也不用等车展、去4s店才能仔细观赏,点开手机就能“置身”车内近距离观看每一处细节,点击关灯开灯、关门关门,除了摸不到,和在现场几乎没有区别; 准备买房的时候,没人愿…

Git 基础(一)—— Git 的安装及其配置

目录 一、Git 的下载与安装 1、Linux 环境 2、Windows 环境 (1) 下载 Git 安装包 (2) 安装 Git 二、Git 配置 1、配置用户信息 2、查看配置信息 3、Windows 环境下配置文件的位置 一、Git 的下载与安装 1、Linux 环境 在保证网络环境畅通的情况下,直接输…

L298N 直流电机驱动模块与 Arduino

L298N 直流电机驱动模块与 Arduino 原文地址 L298N 电机驱动器可以控制两个直流电机的速度和旋转方向。 此外,它还可以控制双极步进电机,例如NEMA 17。如果您想了解更多信息,请查看本教程。 L298N电机驱动器和Arduino控制步进电机&#xff…

基于C/C++综合训练 ----- 贪吃蛇

文章目录一、定义结构体对象二、游戏初始化1. 蛇初始化2. 食物初始化3. 围墙初始化4. 界面初始化三、逻辑编程1. 启动游戏2. 打印成绩3. main函数四、细节处理五、程序源码该篇环境为Visual Studio2022 游戏简述 :在控制终端绘画出一个矩阵表示游戏界面(围墙)&…

android h5餐饮管理系统myeclipse开发mysql数据库编程服务端java计算机程序设计

一、源码特点 android h5餐饮管理系统是一套完善的WEBandroid设计系统,对理解JSP java,安卓app编程开发语言有帮助(系统采用web服务端APP端 综合模式进行设计开发),系统具有完整的源代码和数据库,系统主要…

javaEE初阶 — HTML 中的常见标签

文章目录注释标签标题标签:h1 h6段落标签:p换行标签:br格式化标签图片标签:img1. img 的 alt 属性2. img 的 title 属性3. width 与 heigth 属性用来描述图的尺寸超链接标签:a表格标签列表标签表单标签1. from 标签2. …

【C++的OpenCV】第十一课-OpenCV图像常用操作(八):直方图计算(cv.calc())

🎉🎉🎉欢迎各位来到小白piao的学习空间!\color{red}{欢迎各位来到小白piao的学习空间!}欢迎各位来到小白piao的学习空间!🎉🎉🎉 💖💖&#x1f496…

发布新闻稿的流程与步骤

发布新闻稿需要遵循一定的流程和步骤,以下是一般的新闻发布流程:1、编写新闻稿新闻稿的内容应当简洁、明确、准确,力求突出新闻价值和亮点。企业和组织可以根据新闻稿的主题和目的,选择不同的写作风格和语言表达方式,以…

春季训练营 | 前端+验证直通车-全实操项目实践,履历加成就业无忧

“芯动的offer”是2023年E课网联合企业全新推出集训培优班(线下),针对有一定基础(linux、verilog、uvm等)在校学生以及想要通过短时间的学习进入到IC行业中的转行人士,由资深IC设计工程师带教,通…

openpnp - 贴片前, 放入一块新板子后, 对板子的坐标矫正

文章目录openpnp - 贴片前, 放入一块新板子后, 对板子的坐标矫正概述笔记实验前置条件实验开始建立自己板子上的Mark点封装, 用于自己人工圈定判断Mark点位置是否正确建立mark点封装根据多个mark点, 来精确定位板子左下角原点坐标ENDopenpnp - 贴片前, 放入一块新板子后, 对板子…

图像边缘检测

文章目录前言一、图像边缘检测二、边缘检测算子1. Roberts算子2. Prewitt算子3. Sobel算子三、代码实现总结前言 有了图像放大缩小,图像灰度化处理等相关基础知识过后,就可以进行图像边缘检测了。边缘检测最后也会在FPGA上面实现,此处小编已经…

神经网络分类任务(手写数字识别)

1.Mnist分类任务 网络基本构建与训练方法,常用函数解析 torch.nn.functional模块 nn.Module模块 学习方法:边用边查,多打印,duogua 使用jupyter的优点,可以打印出每一个步骤。 2.读取数据集 自动下载 %matplotl…

移动设备配置文件管理

什么是移动设备上的设备配置文件 随着移动设备在工作中使用量的迅速增加,有必要将这些设备置于企业管理之下,以确保企业数据安全且设备符合行业标准。移动设备上的配置文件允许 IT 管理员通过对员工使用的智能手机、平板电脑和笔记本电脑实施公司策略和…

三维人脸实践:基于Face3D的渲染、生成与重构 <一>

face3d: Python tools for processing 3D face git code: https://github.com/yfeng95/face3d paper list: PaperWithCode 该方法广泛用于基于三维人脸关键点的人脸生成、属性检测(如位姿、深度、PNCC等),能够快速实现人脸建模与渲染。推荐…

学生使用的台灯该怎么选择?2023适合学生房间的灯推荐

随着社会的进步发展,我们的生活水平越来越高,很多家庭的孩子都开始使用台灯这种家居产品,对于学习任务繁重的他们来说,台灯确实可以起到保护眼睛、提高学习专注度的作用。那么不知道朋友们是否了解过,台灯该怎么选择呢…

本地开发vue项目联调遇到访问接口跨域问题

本地开发vue项目联调遇到访问接口跨域问题 修改本地的localhost 一:按winr打开运行窗口,输入drivers ,然后回车 二:打开etc文件夹,然后用记事本的方式打开里面的hosts文件, 三:这时我们就可…

oneblog_justauth_三方登录配置【QQ】

文章目录oneblog添加第三方平台QQ互联平台创建三方应用完善信息登录oneblog添加第三方平台 1.oneblog管理端,点击左侧菜单 网站管理——>社会化登录配置管理 ,添加一个社会化登录 2.编辑信息如下,选择QQ平台后复制redirectUri,然后去QQ互联平台获取…

UART 串口通信

第18.1讲 UART串口通信原理讲解_哔哩哔哩_bilibili 并行通信 一个周期同时发送8bit的数据,占用引脚资源多 串行通信 串行通信的通信方式: 同步通信 同一时钟下进行数据传输 异步通信 发送设备和接收设备的时钟不同 但是需要约束波特率(…

大数据|HDFS分布式文件系统

前文回顾:Hadoop系统 目录 📚HDFS概述 📚HDFS在设计时的假设和目标 📚HDFS的基本特征 📚HDFS的体系结构 🐇目录节点 🐇数据节点 📚HDFS的副本机制 📚HDFS的数据存…