当前位置: 首页 > news >正文

linux学习之线程2:线程控制与使用

铺垫

之前我们提到,Linux不直接对线程进行调度,而是对轻量级进程进行调度。但用户就想像Windows那样直接对线程进程控制。所以,就有了pthread库来封装了一层。

那么想要进行线程控制,要用pthread库。(pthread库是原生线程库,即系统自带的)

原本的线程叫主线程,新创建的叫新线程。

创建线程

pthread_create函数

用于创建新线程来并发执行一个函数

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);pthread_t *thread:指向一个线程标识符 pthread_t 的指针,用于存储新创建的线程的 ID。这个 ID 以后可以用于其他线程操作,如等待线程结束或取消线程。const pthread_attr_t *attr:指向线程属性对象的指针。通过该参数可以设置线程的属性(如是否可被 join、栈大小等)。如果传入 NULL,则使用默认的线程属性。void *(*start_routine)(void *):这是线程要执行的函数的指针。该函数的返回值类型为 void*,参数类型为 void*,即它接受一个通用的指针参数,并返回一个通用指针作为结果。void *arg:传递给 start_routine 函数的参数,它是一个通用指针。可以通过它传递任意类型的数据到线程函数中。

LWP和PID

在这里插入图片描述

我们通过显示线程的详细信息,能看到PID和LWP,
LWP是轻量级进程的ID,实际上我们在调度的时候,使用的都是LWP ID。

getid?

我们用getid()来获得两个线程的id,发现得到的是PID,LWP并没有提供直接获取的方式,比较麻烦。

线程运行与结束顺序

是新线程先运行还是老线程先运行,由调度器决定。
但是当主线程结束之后,进程就会退出,所有线程也就退出了

等待进程

pthread_join 函数

int pthread_join(pthread_t thread, void **retval);pthread_t thread:要等待的线程的标识符,即需要 pthread_join 的线程 ID。这个 ID 是由 pthread_create 创建线程时返回的 pthread_t 类型变量。void **retval:这是一个指向指针的指针,用于存储目标线程的返回值。线程的返回值可以通过 pthread_exit 返回,也可以是线程函数的返回值。如果你不关心返回值,可以传递 NULL

同一进程下的多线程

  1. 同一个进程的线程,资源是共享的
  2. 多线程中,任意一个线程出问题,则进程退出
  3. 并且不用考虑

退出

pthread_exit

用pthread_exit来退出某个进程,谁调用这个函数就退出谁

pthread_cancel

当我们确定这个进程已经启动的时候,我们可以调用pthread_cancel函数,来取消这个线程

线程优点

  • 创建一个新线程的代价要比创建一个新进程小得多(只要创建新的PCB就够了)
  • 与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多(与cache有关)
  • 线程占用的资源要比进程少很多
  • 能充分利用多处理器的可并行数量
  • 在等待慢速I/O操作结束的同时,程序可执行其他的计算任务
  • 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
  • I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作。

cache

线程切换比进程好的关键原因就是cache
cache就是CPU中的缓存,
他会默认存储正在执行代码的下一行代码的地址,方便执行。
线程切换不会影响缓存(前面提到了:因为同一进程中的线程共享相同的地址空间和全局数据。),而进程切换之后,缓存一般需要重新加载。所以

计算密集型和i/o密集型

计算密集型:解压,压缩之类的,使用cpu的资源。
建议cpu有几核,就创建几个线程,太多线程切换起来还要时间
i/o密集型:下载之类的。
可以多开几个,来减少等待时间。

缺点

健壮性降低
编写多线程需要更全面更深入的考虑,在一个多线程程序里,因时间分配上的细微偏差或者因共享了不该共享的变量而造成不良影响的可能性是很大的,换句话说线程之间是缺乏保护的。
缺乏访问控制
进程是访问控制的基本粒度,在一个线程中调用某些OS函数会对整个进程造成影响(因为大部分资源是共享的)

线程用途

线程与进程

线程独占(私有)

线程共享进程数据,但也拥有自己的一部分数据:

  • 线程ID
  • 一组寄存器(一组线程执行的硬件上下文数据,每个线程还是单独的执行流)
  • 栈( 临时数据会压入栈,如果不区分就会很混乱)
  • errno
  • 信号屏蔽字
  • 调度优先级

线程共享

各线程还共享以下进程资源和环境:

  • 代码和全局数据
  • 文件描述符表(记录打开文件的个数)
  • 每种信号的处理方式(SIG_ IGN、SIG_ DFL或者自定义的信号处理函数)
  • 当前工作目录
  • 用户id和组id

在创建新的线程的时候,我们需要为每个线程在堆上开辟一段属于自己的开间,再释放掉。这样就避免

线程的使用

传参和返回值

我们不仅可以给线程传递信息,也可以传递对象来执行某些任务。

cpp11的thread

thread库就是封装了Linux的pthread库

为什么要封装

为了使cpp具有跨平台性(使其在vs下也能跑)

Windows

Windows下不用包含pthread库

其他语言

大部分语言都要用到pthread库

线程分离

当我们不关心新线程的执行信息的时候,我们可以将其设为分离状态。要用到pthread_detach函数

int pthread_detach(pthread_t thread);thread: 这是一个类型为 pthread_t 的线程标识符,表示需要设置为分离状态的线程。如果操作成功,pthread_detach 返回 0。如果失败,返回一个错误码。

注意
分离后的线程不需要join,否则会出错

讨论

那新线程和主线程之间还会相互影响吗,

会的
主线程退出,新线程也会退出,资源依然共享

结论

分离只是一种工作状态,不在意执行结果
底层仍是同一个进程
所以大部分应用软件就是主线程死循环(常驻任务),有新任务的时候,就创建新线程。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 一例pyinstaller打包的cs马鉴赏
  • SprinBoot+Vue校园车辆管理系统的设计与实现
  • (Java企业 / 公司项目)点赞业务系统设计-批量查询点赞状态(二)
  • 【区块链 + 人才服务】Blockchain Workshop- 区块链编程实践平台 | FISCO BCOS应用案例
  • vue3使用leaflet+trackplayer实现非地图动画轨迹(市场平面图动态轨迹)
  • 汇编语言第一次作业
  • Unity:类塔科夫,塔防网格构建
  • Agent、RAG、LangChain的概念及作用
  • spring security 如何解决跨域的
  • js部分面试题
  • 如何通过可视化大屏,打通智慧城市建设的“最后一公里”?
  • crontab命令:定时任务,周期执行
  • ROS2仿真之两轮差速
  • 纵切车床和走心机的区别
  • C/C++ 网络编程之关于多核利用问题
  • Google 是如何开发 Web 框架的
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • 0基础学习移动端适配
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • Angularjs之国际化
  • Apache的基本使用
  • chrome扩展demo1-小时钟
  • Java知识点总结(JavaIO-打印流)
  • OSS Web直传 (文件图片)
  • Python学习之路13-记分
  • Redis字符串类型内部编码剖析
  • spring cloud gateway 源码解析(4)跨域问题处理
  • weex踩坑之旅第一弹 ~ 搭建具有入口文件的weex脚手架
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 给github项目添加CI badge
  • 关于使用markdown的方法(引自CSDN教程)
  • 小程序、APP Store 需要的 SSL 证书是个什么东西?
  • 数据库巡检项
  • ​经​纬​恒​润​二​面​​三​七​互​娱​一​面​​元​象​二​面​
  • !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结
  • # windows 安装 mysql 显示 no packages found 解决方法
  • #100天计划# 2013年9月29日
  • #etcd#安装时出错
  • #pragma once与条件编译
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (32位汇编 五)mov/add/sub/and/or/xor/not
  • (Oracle)SQL优化基础(三):看懂执行计划顺序
  • (Redis使用系列) Springboot 整合Redisson 实现分布式锁 七
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (每日持续更新)jdk api之FileReader基础、应用、实战
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理 第13章 项目资源管理(七)
  • (亲测有效)推荐2024最新的免费漫画软件app,无广告,聚合全网资源!
  • (算法)区间调度问题
  • (转)【Hibernate总结系列】使用举例
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • .NET Compact Framework 多线程环境下的UI异步刷新
  • .Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化