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. 编程复杂度:多进程 < 多线程

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

相关推荐
狼爷15 小时前
Rust/Go/Java/Python/PHP 大比拼:负载下后端框架到底差多少?
java·后端·编程语言
念何架构之路15 小时前
zap扩展生态与总结
java·前端·数据库
沫璃染墨16 小时前
《Linux工程实践篇(一):认识设计模式——从日志系统看策略模式》
linux·c++·安全·设计模式·策略模式
第七页独白16 小时前
汽车零件厂如何通过 QMS 真正落地 IATF 16949——QMS软件系统:品质检验-内审稽核-8d客诉管理:全星质量管理软件系统
java·前端·数据库
工作10年+,存储芯片行业16 小时前
Linux NVMe 中断排查与性能优化:CPU 亲和性
linux·运维·服务器·windows·性能优化·ssd·pcie
QCoding16 小时前
Spring AI Alibaba Graph实战:从ReAct Agent到Workflow,企业AI复杂流程该如何编排?
java·人工智能
用户0942485680316 小时前
第25章:Java虚拟线程(Project Loom)实战与调度协作
java·jvm
砚底藏山河16 小时前
量化实战:截面因子有效性检验(IC 分析与分层回测)
java·python·金融·maven
wuminyu16 小时前
ForkJoinPool内部WorkQueue的Lock-Free数组操作以及并发任务窃取原理剖析
java·linux·c语言·jvm·c++
Elastic 中国社区官方博客16 小时前
使用 Lucene 搜索你的 Bean — 索引
java·大数据·数据库·elasticsearch·搜索引擎·全文检索·lucene