Linux中的线程是什么?

在现代Linux操作系统中,一个程序在运行时,进程是分配资源的基本单位,Linux内核先fork一个子进程,分配物理内存,然后将要执行的可执行文件加载到内存。每个进程都是相互独立的,进程之间如果需要通信则需要借助第三方工具。

不同的进程在切换运行时,CPU需要不停地保存现场、恢复现场,因此进程上下切换的开销是很大的。所以如果程序要并行执行很多任务,通过创建很多的进程来实现,不是个很好的主意。在现代linux操作系统中引入了线程,它的目的是为了减少进程的开销,就是减少进程的切换。一个进程可能存在多个线程,但它至少有一个线程。多个线程之间的关系就像在一个家里一样,每个人都有自己的房间,但饭厅、客厅、卫生间都是公用的。多个线程都有各自独立的资源,如程序计数器、寄存器上下文和各自的栈空间;但是进程中的代码段、数据段、地址空间、打开的文件、信号处理程序等资源都是共享的。这些共享的资源为了保证程序的正确性符合逻辑,这共享资源会涉及安全访问和线程间同步的问题,一般通过互斥锁、条件锁、读写锁等锁机制来实现对资源的安全访问。这是很好理解的,就像在家里的厕所有人正在使用,其他人就要等。

在C语言中,使用pthread库来实现多线程对共享资源的互斥访问:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 初始化互斥锁

int shared_num = 0; // 共享资源

void* thread_task(void* arg) {

pthread_mutex_lock(&mutex); // 加锁

shared_num++;

printf("共享变量值:%d\n", shared_num);

pthread_mutex_unlock(&mutex); // 解锁

pthread_exit(NULL); //退出程序

复制代码
加锁也会增加系统开销,即当程序调用加锁函数时,操作系统会从用户态切换到内核态,并阻塞在内核态;当程序调用解锁时,也经历从用户态切换到内核态,再从内核态切换回用户态。这告诉我们如果减少此类开锁,就要减少加锁、解锁的操作。

我们再来说说线程池,虽然进程的多个线程可以共享进程的很多资源,如代码段、数据段、打开的文件,线程们也有自己的上下文环境,如各自的寄存器状态、栈、程序计数器等。在现代linux系统里,进程是资源分配的基本单元,而线程则是程序执行和调试的最小单元。线程的开锁除了线程上下文 切换带来的开销外,这里还有另一个开销,那就是线程的创建与销毁,尤其是频繁使用线程的场景下,这种开销会特别明显。

为了减少线程不断创建与销毁带来的开销,可以实现一个线程池。预先创建一些线程,没有任务时,这些线程就阻塞在池中,有任务时,通过管理线程将任务分配到指定的线程来执行。

一般来说实现一个线程池需要有管理线程、工作线程和任务接口等组成。管理线程是用于创建和管理工作线程的,将用户创建的不同任务分配给不同的工作线程去执行;工作线程是真正做事的线程,它负责执行给过来的伤,没有任务时,就阻塞中池中。线程池一般会提供一些任务接口供用户创建不同的任务,这些任务会分配到不同的线程中去执行。

相关推荐
LaoZhangGong1231 小时前
以太网HTTP数据包格式分析
c语言·stm32·网络协议·http·tcp·arp
lingggggaaaa3 小时前
免杀对抗——C2远控篇&PowerShell&有无文件落地&C#参数调用&绕AMSI&ETW&去混淆特征
c语言·开发语言·笔记·学习·安全·microsoft·c#
口袋物联3 小时前
设计模式之建造者模式在 C 语言中的应用(含 Linux 内核实例)
c语言·设计模式·建造者模式
切糕师学AI4 小时前
位带操作(Bit-Banding)是什么?
c语言·arm·嵌入式开发·cortex-m·位带操作
学习路上_write4 小时前
嵌入式系统bringup指南:软硬件调试
c语言·单片机·嵌入式硬件
say_fall4 小时前
C语言编程实战:每日一题 - day7
c语言·开发语言
小龙报4 小时前
《算法通关指南数据结构和算法篇(2)--- 链表专题》
c语言·数据结构·c++·算法·链表·学习方法·visual studio
醉颜凉5 小时前
环形房屋如何 “安全劫舍”?动态规划解题逻辑与技巧
c语言·算法·动态规划
望眼欲穿的程序猿5 小时前
Win系统Vscode+CoNan+Cmake实现调试与构建
c语言·c++·后端