Linux软件编程(5)线程

前两天学习完了进程有关的内容,今天学习线程这部分的内容,线程和进程很容易搞混,我们还是要搞懂定义,但是学习完了进程,线程这部分内容相对容易理解。

一、什么是线程

线程被叫做轻量级进程,它同样拥有创建、调度、消亡完整流程。

进程和线程的区别:

进程:操作系统资源分配的最小单位

每个进程拥有0‑4G完整虚拟内存空间,分为文本段、数据段、堆等区域,进程之间内存互相独立,互不干扰。

线程:操作系统任务调度的最小单位

线程跑在进程的地址空间里面。同一个进程里的多个线程,共享堆、全局变量、静态变量、字符串常量、代码段;但是每个线程有自己独立的栈空间,局部变量是线程私有的。

简单总结:

进程拥有整套资源;线程只拥有自己栈,其余全部借用父进程的资源。

二、进程与线程核心函数对比

进程 线程

fork() 创建 pthread_create() 创建

exit() 退出 pthread_exit() 退出

wait() 回收子进程 pthread_join() 回收线程

  1. 调度

    线程调度和进程调度规则一致,宏观上看多个线程并发运行,微观上CPU分片交替执行。

  2. 线程消亡

    线程结束之后,如果不调用pthread_join回收资源,就会产生僵尸线程,占用系统资源。

三、线程函数

编译线程程序必须加 -pthread 参数,gcc test.c -o test -pthread。

  1. pthread_create 创建线程

    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,

    void *(*start_routine) (void *), void *arg);

    功能:

    创建线程。

    参数:

    thread:传出参数,存放新线程ID(TID)

    attr:线程属性,一般传NULL,使用默认属性

    start_routine:线程要执行的函数,函数指针

    arg:传给线程函数的参数

    返回值:

    成功返回0,失败返回错误码

    调用完这个函数,新线程立刻开始调度,主线程和子线程谁先跑是不确定的。

  2. pthread_exit 结束线程

    void pthread_exit(void *retval);

    功能:

    用来在线程函数内部结束当前线程。

    参数:

    retval是线程退出的状态值,可以被pthread_join拿到。

    注意:不要在线程里面直接用exit(),exit会把整个进程直接结束,所有线程全部消失。

  3. pthread_join 回收线程

    int pthread_join(pthread_t thread, void **retval);

    功能:

    等待指定线程结束,回收线程栈资源,具备阻塞特性。

    参数:

    thread:要等待回收的线程ID

    retval:接收线程退出返回值,不需要接收就填NULL

    返回值:

    成功0,失败返回错误码

    阻塞含义:如果子线程还没跑完,主线程卡在join这里原地等待,直到子线程结束才往下走。

    四、分离属性 detach(不用join回收)

普通线程必须pthread_join回收,否则僵尸线程。

设置分离属性之后:线程结束,操作系统自动回收资源,程序就不需要调用pthread_join。

相关接口:

  1. pthread_attr_init:初始化线程属性结构体
  2. pthread_attr_setdetachstate:设置分离状态
  3. pthread_attr_destroy:销毁属性结构体,释放空间

两种写法:创建的时候设置分离属性;或者线程内部调用pthread_detach(self)。

五、多进程 、多线程的优缺点

  1. 运行效率:多线程 > 多进程

线程共享进程地址空间,创建切换开销小;进程要复制完整内存,开销更大。

  1. 安全性:多进程 > 多线程

进程内存完全独立,一个进程崩溃,不会影响别的进程。

同一个进程内,任意一个线程崩溃,整个进程直接挂掉,全部线程一起结束。

  1. 通信实现:多线程 > 多进程

多线程天然共享全局变量、堆内存,直接读写就可以通信。

但是多个线程同时改共享变量,会出现资源竞争,需要加锁保护。

多进程地址空间互相隔离,没有共享内存,必须管道、共享内存这类特殊机制才能通信,实现复杂。

  1. 编程复杂度:多进程 < 多线程

多线程要处理资源竞争、锁、僵尸线程;多进程通信麻烦,但不会出现线程互相干扰的问题。

相关推荐
数据知道24 分钟前
Java 安全审计实战:SSRF、反序列化、SpEL 注入
java·开发语言·安全·网络安全
mounter62526 分钟前
重构 Kexec Handover:Linux 内核如何将 KHO 打造为无状态、可重入的跨重启交接基石
linux·内存管理·linux kernel·kernel·liveupdate
嗝屁小孩纸29 分钟前
通用后端基础能力平台(多模块技术总结与避坑指南)
java
CodeStats32 分钟前
【Java 表达式引擎】如何设计一套 Java 表达式引擎:从递归下降到 AST 求值的完整实践
java·ai编程·表达式·引擎
vipxieliang1 小时前
ValidX错误消息国际化完全指南:8种语言9个语言包与三级回退机制
java·spring boot
杨云龙UP1 小时前
Linux 下 MySQL 常用登录方式及 Socket 排查指南
linux·运维·数据库·mysql·登录·xtrabackup·主从复制
xbgRS1 小时前
RocketMQ消费者消息获取
java·rocketmq·java-rocketmq
云和数据.ChenGuang1 小时前
git revert回退问题
java·服务器·人工智能·git·fastapi·强化学习
鱼很腾apoc1 小时前
【Linux】第13期 详解应用层协议HTTP+Cookie/Session+HTTPS
linux·服务器·c++·学习·http·https