线程的概念
序言
在之前的文章中,我们介绍了进程的概念,在该文章中我们提到了 进程 = PCB + 代码数据,这只是进程的组成,并不是真正进程的概念!因为只是单独介绍概念不结合今天的主角 线程,可能不是那么容易理解。
在这篇文章中,我们将介绍 线程,让大家理解进程和线程之间的区别,联系,以及简单的线程控制。
1. 再看进程
1.1 回顾进程
进程是程序在操作系统的一次执行过程,当一个程序被加载到内存中并由操作系统执行时,它就成为了一个进程。 但是进程 != 代码和数据 ,为了更好地管理所有需要执行的程序,创建了一个包含了自身信息的结构体,叫做 PCB 进程控制块。所以说,进程 = PCB + 代码数据。
1.2 进程的新概念
除了上述的我们已经知道的,现在我们还需要知道 进程是系统进行资源分配和调度的一个独立单元。简而言之,进程是程序执行时的一个实例,是系统进行资源分配和调度的一个独立单元。
我们怎么来理解这句话呢,我们想一下,操作系统通过进程来管理和控制各种资源的使用。系统通过为每个进程分配适当的资源(如CPU时间、内存空间、文件、I/O设备等),确保进程能够正常运行。同时,系统还通过一系列的控制机制(如进程同步、互斥、通信等)来协调进程间的资源使用和竞争,以维持系统的稳定性和性能。
2. 线程
2.1 线程的概念
线程是进程中的一个实体,是 CPU 调度和分派的基本单位,它是 进程中的实际运作单位。线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器、一组寄存器和栈),但它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
大家在这里可能有一点蒙圈,我们在运行程序时,都是说该程序是以进程的形式存在于内存中,怎么变成线程去执行我们的程序呢?给大家举个例子吧,有两个公司,其中一个是小公司,业务逻辑非常简单,只需要一个人执行就完全没问题了(这里只是例子,笔者也不知道有没有一个人的公司 哈哈),而另一个是大公司,业务逻辑非常复杂,于是创建了许多部门,每一个部门的业务都不同,但是所有部门的联合才造就了公司的正常运行!!!
所以,我们之前写的程序就类似于第一个公司,我们的进程中只包含一个线程(也称执行流),但是确实存在一些复杂的程序,需要多线程(多个执行流)完成任务。
2.1 多线程的特点
多个线程工作时,同在一个屋檐下(在同一个进程中),操作系统中为了更好的管理所有的进程创建了 PCB,存储进程相关的信息。所以一样的,为了更好的管理线程,创建了 线程控制块 TCB 来管理线程。
多线程工作时,具有以下特点:
1. 并发性
同时执行:多线程能够使得程序中的多个任务并行执行,而不是顺序执行。这意味着在同一时间内,CPU可以交替地执行多个线程中的指令,从而提高了程序的并发性。资源共享:多线程共享进程的地址空间和资源,这使得线程间的通信和数据共享变得更为方便和高效。在这里罗列一下什么资源会共享,而哪些不共享:
| 资源类型 | 描述 | 是否共享 |
|---|---|---|
| 代码区 | 编译后的可执行机器指令 | 是 |
| 数据区 | 全局变量和静态变量 | 是 |
| 堆区 | 动态分配的内存区域(逻辑上共享,实际需同步保护) | 是 |
| 栈区 | 存储局部变量、函数调用参数和返回值 | 否 |
| 寄存器 | 存储中间结果和状态信息 | 否 |
| 程序计数器 | 记录线程当前执行的指令地址 | 否 |
| 调度优先级 | 控制线程的执行优先级 | 否 |
| 文件描述符 | 访问打开文件的标识符 | 是 |
| 文件访问权限 | 访问文件的权限 | 是 |
| 系统资源(如共享内存段) | 根据资源类型和配置,可能共享也可能不共享 | 是 |
| 环境变量 | 进程的环境设置 | 是 |
| 命令行参数 | 启动进程时传递的参数 | 是 |
2. 独立性
独立调度:在操作系统中,线程是独立调度的基本单位。每个线程都有自己的执行流和生命周期,可以独立地被创建、执行、暂停和终止。独立堆栈:每个线程都有自己独立的堆栈空间,用于存储局部变量和调用栈等信息。这保证了线程间的独立性,避免了数据混淆和冲突。
2.3 Linux 上的线程
不同系统上,实现线程的方式各有差异,在这里我们介绍在 Linux 上的线程。
其实在 Linux 系统上,并不存在真正意义上的线程,这是因为Linux中的线程实际上是通过模拟进程来实现的,被称为 轻量级进程。
为什么这样做呢?在 Linux 中,线程和进程都使用相同的内核数据结构(task_struct)来表示(以统一的视角看待进程线程),这使得 线程和进程在内核中具有高度的统一性。这种设计简化了内核的实现,因为它不需要为线程和进程分别维护不同的 数据结构和管理机制。(说白了,这种方式省时又省事!!!)多个线程共享一个进程地址空间,所以又叫做 轻量级进程。
3. 多进程 PK 多线程
在之前的学习中,我们知道我们也可以使用多进程处理业务逻辑比较复杂的任务,那这两者的区别,优劣是什么呢?
3.1 优点
1. 多进程的优点
独立性:每个进程都有独立的内存空间和系统资源,如文件描述符、网络连接等。这种独立性使得一个进程的崩溃不会影响其他进程的运行,从而提高了系统的稳定性和可靠性。安全性:由于进程间的内存和资源相互隔离,一个进程中的错误或异常操作很难影响到其他进程,这增强了系统的安全性。可扩展性:多进程可以更好地利用多核处理器的优势,每个进程可以在不同的CPU核心上运行,实现真正的并行计算,提高程序的执行效率。
2. 多线程的优点
资源共享:同一进程内的所有线程共享该进程的内存空间和系统资源,这使得线程间的数据交换和通信更加方便和高效。切换开销小:线程之间的切换相对于进程来说开销较小,因为线程只需要保存和恢复少量的上下文信息(如栈指针、程序计数器等)。响应速度快:多线程可以实现并发处理,能够更快地响应用户的请求,提高系统的交互性能。编程简单:相对于多进程编程,多线程编程的复杂性较低,因为同一进程内的线程可以直接共享数据,通信和同步更加方便。
3.2 缺点
1. 多进程缺点
资源消耗:每个进程都需要独立的内存空间和系统资源,这会导致系统资源的浪费。当进程数量过多时,系统资源可能不足以支持所有进程的运行。切换开销:进程之间的切换需要保存和恢复大量的上下文信息,包括程序计数器、寄存器、栈等,这会导致较大的切换开销,影响程序的执行效率。
-通信开销:进程间通信(IPC)通常比较复杂且开销较大,需要使用特定的机制(如管道、消息队列、共享内存等)来实现,增加了编程的复杂性和运行时的开销。
2. 多线程缺点
数据安全问题:多个线程同时访问共享数据时可能会引发数据竞争和不一致的问题,需要使用同步机制(如锁、信号量等)来保证数据的安全性,但这也可能导致死锁和性能下降等问题。调试和测试困难:多线程程序的调试和测试相对复杂,因为多个线程同时运行,线程之间的交互和状态变化较为复杂,导致问题的追踪和定位更加困难。健壮性差:当多个线程同时工作时,如果一个线程因为某种原因崩溃,会使整个进程被终止,总之一个线程中的错误或异常操作会影响到其他线程。
4. 总结
在这篇文章中,我们首先回顾了进程的概念,其次学习了线程的概念以及现成的特点,最后比较了多进程多线程任务的优劣,希望大家有所收获😄。
