什么是线程?

线程

1. 线程概述

线程是计算机科学中的基本概念,指的是在一个进程中执行的独立指令流。通常,一个进程可以包含多个线程,它们共享进程的资源,如内存空间、文件句柄等,但每个线程有自己的独立执行流。线程是操作系统进行调度的最小单元(进程是资源分配的最小单位),它由线程标识符、程序计数器、寄存器集合和堆栈组成。

与进程不同,**线程之间可以更轻松地共享数据和通信,因为它们属于同一个进程,共享相同的地址空间。**这使得线程在并发编程中更为灵活,可以用于实现多任务并行执行。多线程的优点包括提高程序的响应性、资源共享和更高的系统利用率。

然而,多线程编程也带来了一些挑战,如竞态条件(Race Condition)、死锁(Deadlock)等问题,因此在设计和实现多线程程序时需要仔细考虑线程之间的同步和互斥。

进程和线程的区别:

进程有自己独立的地址空间, 多个线程共用同一个地址空间

  • 线程更加节省系统资源, 效率不仅可以保持的, 而且能够更高
  • 在一个地址空间中**多个线程独享: 每个线程都有属于自己的栈区, 寄存器(**内核中管理的)
  • 在一个地址空间中**多个线程共享: 代码段, 堆区, 全局数据区, 打开的文件(文件描述符表)**都是线程共享的

线程是程序的最小执行单位, 进程是操作系统中最小的资源分配单位

  • 每个进程对应一个虚拟地址空间,一个进程只能抢一个CPU时间片
  • 一个地址空间中可以划分出多个线程, 在有效的资源基础上, 能够抢更多的CPU时间片

在这里插入图片描述

  • CPU的调度和切换: 线程的上下文切换比进程要快的多

上下文切换:进程/线程分时复用CPU时间片,在切换之前会将上一个任务的状态进行保存, 下次切换回这个任务的时候, 加载这个状态继续运行,任务从保存到再次加载这个过程就是一次上下文切换

  • 线程更加廉价, 启动速度更快, 退出也快, 对系统资源的冲击小。

在处理多任务程序的时候使用多线程比使用多进程要更有优势,但是线程并不是越多越好,如何控制线程的个数呢?

  1. 文件IO操作:文件IO对CPU是使用率不高, 因此可以分时复用CPU时间片, 线程的个数 = 2 * CPU核心数 (效率最高)
  2. 处理复杂的算法(主要是CPU进行运算, 压力大),线程的个数 = CPU的核心数 (效率最高)

2. 线程相关函数

  • 获取线程id
pthread_t pthread_self(void);	// 返回当前线程的线程ID
  • 创建线程
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
// Compile and link with -pthread, 线程库的名字叫pthread, 全名: libpthread.so libptread.a

参数:

  • thread: 传出参数,是无符号长整形数,线程创建成功, 会将线程ID写入到这个指针指向的内存中
  • attr: 线程的属性, 一般情况下使用默认属性即可, 写NULL
  • start_routine: 函数指针,创建出的子线程的处理动作,也就是该函数在子线程中执行
  • arg: 作为实参传递到 start_routine 指针指向的函数内部

返回值:线程创建成功返回0,创建失败返回对应的错误号

  • 线程退出

在编写多线程程序的时候,如果想要让线程退出,但是不会导致虚拟地址空间的释放(针对于主线程),我们就可以调用线程库中的线程退出函数,只要**调用该函数当前线程就马上退出了,并且不会影响到其他线程的正常运行,不管是在子线程或者主线程中都可以使用。**

#include <pthread.h>
void pthread_exit(void *retval);

参数: 线程退出的时候携带的数据,当前子线程的主线程会得到该数据。如果不需要使用,指定为NULL

  • 线程回收

线程库中提供的线程回收函叫做pthread_join(),这个函数是一个阻塞函数,如果**还有子线程在运行,调用该函数就会阻塞,子线程退出函数解除阻塞进行资源的回收,**函数被调用一次,只能回收一个子线程,如果有多个子线程则需要循环进行回收。

#include <pthread.h>
// 这是一个阻塞函数, 子线程在运行这个函数就阻塞
// 子线程退出, 函数解除阻塞, 回收对应的子线程资源, 类似于回收进程使用的函数 wait()
int pthread_join(pthread_t thread, void **retval);

参数:

  • thread: 要被回收的子线程的线程ID
  • retval: 二级指针, 指向一级指针的地址, 是一个传出参数, 这个地址中存储了pthread_exit() 传递出的数据,如果不需要这个参数,可以指定为NULL

返回值:线程回收成功返回0,回收失败返回错误号。

  • 线程分离

如果让主线程负责子线程的资源回收,调用pthread_join()只要子线程不退出主线程就会一直被阻塞,主要线程的任务也就不能被执行了。

**在线程库函数中为我们提供了线程分离函数pthread_detach(),调用这个函数之后指定的子线程就可以和主线程分离,当子线程退出的时候,其占用的内核资源就被系统的其他进程接管并回收了。**线程分离之后在主线程中使用pthread_join()就回收不到子线程资源了。

#include <pthread.h>
// 参数就子线程的线程ID, 主线程就可以和这个子线程分离了
int pthread_detach(pthread_t thread);

代码演示:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>void* callbackFunc(void* arg) {printf("son thread id: %d\n", pthread_self());pthread_exit(NULL);
}int main() {printf("main thread id: %d\n", pthread_self());pthread_t mythread;// 创建新线程  返回0 表示成功int res = pthread_create(&mythread, NULL, callbackFunc, NULL);if (res) {printf("error creating thread:%d\n", res);return -1;}sleep(2);// 主线程等待新线程结束// pthread_join(mythread, NULL);pthread_detach(mythread);printf("Back in the main thread.\n");return 0;
}

执行结果:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

档案统一管理的具体做法包括哪些?

档案统一管理工作&#xff0c;需要根据统管单位工作特点重建管理流程&#xff0c;优化和规范管理。档案统一管理的具体做法包括&#xff1a; 1. 设立档案管理部门或档案管理团队&#xff0c;负责统一管理机构的所有档案资料。 2. 建立档案管理制度和流程&#xff0c;明确档案的…

数字战场上的坚固屏障:雷池社区版(WAF)

黑客的挑战 智能语义分析算法&#xff1a; 黑客们常利用复杂技术进行攻击&#xff0c;但雷池社区版的智能语义分析算法能深入解析攻击本质&#xff0c;即使是最复杂的攻击手法也难以逃脱。 0day攻击防御&#xff1a; 传统防火墙难以防御未知攻击&#xff0c;但雷池社区版能有效…

【Linux Shell】5. 运算符

文章目录 【 1. 算术运算符 】1.1 expr 命令1.2 [ ] 方括号 【 2. 关系运算符 】【 3. 布尔运算符 】【 4. 逻辑运算符 】【 5. 字符串运算符 】【 6. 文件测试运算符 】 【 1. 算术运算符 】 运算符说明举例赋值a$b 把变量 b 的值赋给 a。 1.1 expr 命令 原生 bash 不支持简…

vue 自定义网页图标 favicon.ico 和 网页标题

效果预览 1. 添加配置 vue.config.js 在 module.exports { 内添加 // 自定义网页图标pwa: {iconPaths: {favicon32: "./favicon.ico",favicon16: "./favicon.ico",appleTouchIcon: "./favicon.ico",maskIcon: "./favicon.ico",msTil…

详解c++移动构造函数和移动赋值运算符在代码性能中的作用

对象移动 对象移动&#xff0c;就是把一个不想用了的对象A中的一些有用的数据提取出来&#xff0c;在构建新对象B的时候就不需要重新构建对象中的所有数据——从不想用了的对象A中提取出来的有用数据在构建对象B时都可以拿来使用。 我们知道&#xff0c;拷贝构造函数、拷贝赋…

openGauss学习笔记-193 openGauss 数据库运维-常见故障定位案例-备机卡住-数据库只读

文章目录 openGauss学习笔记-193 openGauss 数据库运维-常见故障定位案例-备机卡住-数据库只读193.1 switchover操作时&#xff0c;主机降备卡住193.1.1 问题现象193.1.2 原因分析193.1.3 处理办法 193.2 磁盘空间达到阈值&#xff0c;数据库只读193.2.1 问题现象193.2.2 原因分…

基于深度学习的果蔬检测识别系统(含UI界面、yolov5、Python代码、数据集)

项目介绍 项目中所用到的算法模型和数据集等信息如下&#xff1a; 算法模型&#xff1a;     yolov5 yolov5主要包含以下几种创新&#xff1a;         1. 添加注意力机制&#xff08;SE、CBAM、CA等&#xff09;         2. 修改可变形卷积&#xff08;DySnake-主…

rocketmq查看消息堆积

第一种方式&#xff1a;命令行方式&#xff1a; //查看消费者情况&#xff0c;192.168.2.210为自己mq的地址&#xff0c;回显的Diff Total参数就是堆积的消息数量 ./mqadmin consumerProgress -n 192.168.2.210:9876第二种方式&#xff0c;通过控制台&#xff1a; 回显中的Di…

一点一点,照亮你的美

一、实验要求 当鼠标点击屏幕时&#xff0c;随机出现大大小小的星星闪烁&#xff0c;犹如夜晚的星空 二、实验思路 设置图片的大小 设置事件&#xff08;当鼠标点一下&#xff0c;获取一张图片&#xff09; 设置图片的位置 设置鼠标的位置和图片的相对位置 设置随机大小 …

AI老照片修复-Bringing-Old-Photos-Back-to-Life

&#x1f3e1; 个人主页&#xff1a;IT贫道-CSDN博客 &#x1f6a9; 私聊博主&#xff1a;私聊博主加WX好友&#xff0c;获取更多资料哦~ &#x1f514; 博主个人B栈地址&#xff1a;豹哥教你学编程的个人空间-豹哥教你学编程个人主页-哔哩哔哩视频 目录 1. AI老照片修复原理-…

leetcode 动态规划(最后一块石头的重量II、目标和、一和零)

1049.最后一块石头的重量II 力扣题目链接(opens new window) 题目难度&#xff1a;中等 有一堆石头&#xff0c;每块石头的重量都是正整数。 每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < …

Low Poly Cartoon House Interiors

400个独特的低多边形预制件的集合,可以轻松创建高质量的室内场景。所有模型都已准备好放入场景中,并使用一个纹理创建,以提高性能!包含演示场景! 模型分类: - 墙壁(79件) - 地板(28块) - 浴室(33个) - 厨房(36件) - 厨房道具(68件) - 房间道具(85件) - 灯具(…