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系统里,进程是资源分配的基本单元,而线程则是程序执行和调试的最小单元。线程的开锁除了线程上下文 切换带来的开销外,这里还有另一个开销,那就是线程的创建与销毁,尤其是频繁使用线程的场景下,这种开销会特别明显。

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

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

相关推荐
铅笔小新z1 天前
【C语言】操作符
c语言
by209991 天前
从 malloc/free 到 new/delete:真正理解 C++ 中的内存管理与对象生命周期
c语言·c++·经验分享·动态内存管理
额额额对了1 天前
SPI通信
linux·c语言·汇编·单片机·嵌入式硬件·arm
Logic1011 天前
C语言/数据结构位运算题解:异或XOR找出书柜中编号只出现一次的那一层——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
Logic1011 天前
C语言/数据结构位运算题解:异或XOR找出星球探险中的“独特能量石“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
Escalating_xu1 天前
【C 语言】深入理解指针(3):字符指针、数组指针、二维数组传参、函数指针与转移表
java·c语言·开发语言
垆边人似月.1 天前
华为机考题:最小代价爬楼梯
c语言·c++
垆边人似月.1 天前
华为机考题:二叉树的最大路径和
c语言·c++
程序猿编码1 天前
不用 PyTorch!纯 C 实现 N 维张量 + 反向传播,完成手写数字识别训练
c语言·人工智能·pytorch·神经网络·卷积神经网络·大模型推理
Navigator_Z1 天前
LeetCode //C - 1269. Number of Ways to Stay in the Same Place After Some Steps
c语言·算法·leetcode