;六个问题弄懂线程与进程

csdiy实验

1.有了进程之后为什么发明线程

进程最开始负责两块功能

  • 资源占有:拥有独立的内存空间和I/O资源
  • 执行单元:在CPU执行指令

[!CAUTION]

后来人们发现这样太笨重了,如果我需要一个程序内部的功能同时运行(比如一边打字一边自动保存一边代码审查),就需要创建多个进程,但这样做系统开销非常大。

采用任务细分的思想,人们设计了线程,把存储和执行分开。

此后进程就像是一个资源容器,负责提供地址空间、文件、锁等资源。

而线程就负责当轻量级的活动者,只负责在CPU上执行代码。它需要拥有的是保证它能运行的最小资源:一组寄存器、一个栈、一个状态

[!IMPORTANT]

所以进程像工厂,线程像工人。

这里你是不是可以理解:

  • 线程更好的实现了并发
  • 线程极大的减小了系统开销

2.进程负责实现代码吗?

不是

[!WARNING]

有个常见误解进程是正在运行的程序,所以它当然是在执行代码

从第一个问题可以看出,在现代操作系统中:

  • 进程是资源拥有的基本单位(管理内存、文件、外设等)。
  • 线程是CPU调度和分派的基本单位(真正在CPU上执行指令)。

[!IMPORTANT]

所以一个“正在运行的进程”,本质上是该进程内的至少一个线程正在被CPU执行

3.进程和线程是否有自己独立的内存空间,为什么这么设计?

它们都有内存空间,但是前者是独立,后者是共享。

同一进程内的所有线程共享该进程的整个内存空间(代码段、数据段、堆等)。每个线程只独立拥有:

  • 一组寄存器的值(硬件上下文)
  • 一个(存放局部变量、函数调用信息)

进程是因为需要安全和隔离相互不干扰、独立崩溃、数据私密

而进程是因为需要高效的通信和切换。符合轻量化设计理念。

4.进程和线程的崩溃有什么区别?为什么会有这个区别?

一个进程崩溃了,一般不会影响其他进程

但是一个线程崩溃了,往往会导致它所属的整个进程崩溃

原因就是第三个问题提到的,进程有自己独立的内存空间,而线程是共享的。

  • 进程之间:拥有独立的内存空间。一个进程崩溃后,操作系统回收其占用的资源,其他进程的内存不受任何影响。
  • 线程之间:共享所属进程的整个内存空间。当一个线程执行非法操作(如访问野指针、数组越界、除零、栈溢出)时,会破坏进程的地址空间。操作系统检测到该进程的内存被破坏或产生非法访问,为了系统稳定,会终止整个进程

5.线程被称为“轻量级进程”这个说法对吗?

[!WARNING]

在调度层面成立,在资源层面不成立

准确的方面

  1. 线程和进程都是执行流,有程序计数器、寄存器、栈。
  2. 进程是对程序的“隔离拆分”,线程是对进程的“并发拆分”。
  3. 线程和进程都有状态(就绪、运行、阻塞等)。
  4. 线程和进程都是调度实体(虽然现代OS以线程为调度单位)。

**可能造成的误解:

  1. 资源拥有:进程拥有独立资源;线程不拥有资源,共享进程的资源。
  2. 独立性:进程之间高度独立;同一进程内的线程紧密耦合,一个崩溃影响整个进程。
  3. 切换开销:进程切换重,线程切换轻。
  4. 创建开销:进程创建需要复制/分配资源表、内存空间;线程只需要创建栈和TCB。

6.线程切换比进程切换快,那是否任何时候都该用多线程而不是多进程

[!IMPORTANT]

不是,需要隔离和安全用进程,需要高效协作用线程。

多进程更合适的场景

  1. 需要高可靠性和隔离性:如Chrome浏览器每个标签页独立进程,一个崩溃不影响其他。
  2. 安全性要求高:不同用户、不同权限的任务,进程间隔离防止数据泄露。
  3. 分布式/多机系统:进程可以跨机器运行,线程不能跨机器。
  4. 任务独立性高、交互少:如编译多个源文件。

多线程更合适的场景

  1. 需要频繁共享数据:如生产者-消费者模型。
  2. I/O密集且有交互:如GUI程序(一边响应点击,一边后台计算)。
  3. 需要低开销并发:创建和切换频繁的场景。

站内搜索
常搜: