当前位置: 代码迷 >> 综合 >> 【通俗易懂】理解进程(process), 线程(thread), 并发(concurrency), 并行(parallel)
  详细解决方案

【通俗易懂】理解进程(process), 线程(thread), 并发(concurrency), 并行(parallel)

热度:4   发布时间:2024-01-06 07:24:33.0

前言

1. 进程 和 线程 的通俗比喻

进程(process)和线程(thread)是操作系统的基本概念。

假定工厂的电力有限,一次只能供给一个车间使用。也就是说,一个车间开工的时候,其他车间都必须停工。背后的含义就是,单个CPU一次只能运行一个任务。进程 就好比工厂的车间,它代表CPU所能处理的单个任务。任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。一个车间里,可以有很多工人。他们协同完成一个任务。线程 就好比车间里的工人。

一个进程可以包括多个线程。车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的。这象征一个进程的内存空间是共享的,每个线程都可以使用这些共享内存。可是,每间房间的大小不同,有些房间最多只能容纳一个人,比如厕所。里面有人的时候,其他人就不能进去了。这代表一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。一个防止他人进入的简单方法,就是门口加一把锁。先到的人锁上门,后到的人看到上锁,就在门口排队,等锁打开再进去。这就叫 “互斥锁”(Mutual exclusion,缩写 Mutex),防止多个线程同时读写某一块内存区域。还有些房间,可以同时容纳n个人,比如厨房。也就是说,如果人数大于n,多出来的人只能在外面等着。这好比某些内存区域,只能供给固定数目的线程使用。这时的解决方法,就是在门口挂n把钥匙。进去的人就取一把钥匙,出来时再把钥匙挂回原处。后到的人发现钥匙架空了,就知道必须在门口排队等着了。这种做法叫做 “信号量”(Semaphore),用来保证多个线程不会互相冲突。不难看出,mutex是semaphore的一种特殊情况(n=1时)。也就是说,完全可以用后者替代前者。但是,因为mutex较为简单,且效率高,所以在必须保证资源独占的情况下,还是采用这种设计。

操作系统的设计,因此可以归结为三点:

  1. 以多进程形式,允许多个任务同时运行;
  2. 以多线程形式,允许单个任务分成不同的部分运行;
  3. 提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。

首先来一句概括的总论进程 是资源分配的最小单位,线程 是CPU调度的最小单位。

【进程】

1. 进程的优点

  • 顺序程序的特点:具有封闭性和可再现性;
  • 程序的并发执行和资源共享。多道程序设计出现后,实现了程序的并发执行和资源共享,提高了系统的效率和系统的资源利用率。

2. 进程的缺点

  • 操作系统调度切换多个线程要比切换调度进程在速度上快的多。而且进程间内存无法共享,通讯也比较麻烦。
  • 线程之间由于共享进程内存空间,所以交换数据非常方便;在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。

【线程】
(a) 线程的优点

  • 它是一种非常”节俭”的多任务操作方式。在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种”昂贵”的多任务工作方式。而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间,而且,线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。当然,在具体的系统上,这个数据可能会有较大的区别;
  • 线程间方便的通信机制,由于同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便;
  • 使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上;

(b) 线程的缺点

  • 调度时, 要保存线程状态,频繁调度, 需要占用大量的机时;
  • 程序设计上容易出错(线程同步问题)。

2. 多进程 和 多线程 的优缺点

(1)多进程的优点

  • 每个进程互相独立,不影响主程序的稳定性,子进程崩溃没关系;
  • 通过增加CPU,就可以容易扩充性能;
  • 可以尽量减少线程加锁 / 解锁的影响,极大提高性能,就算是线程运行的模块算法效率低也没关系;
  • 每个子进程都有例如2GB地址空间和相关资源,总体能够达到的性能上限非常大。

(2)多进程的缺点

  • 逻辑控制复杂,需要和主程序交互;
  • 需要跨进程边界,如果有大数据量传送,就不太好,适合小数据量传送、密集运算;
  • 多进程调度开销比较大;

(a) 多线程的优点

  • 无需跨进程边界;
  • 程序逻辑和控制方式简单;
  • 所有线程可以直接共享内存和变量等;
  • 线程方式消耗的总资源比进程方式好;

(b) 多线程的缺点

  • 每个线程与主程序共用地址空间,受限于2GB地址空间;
  • 线程之间的同步和加锁控制比较麻烦;
  • 一个线程的崩溃可能影响到整个程序的稳定性;
  • 到达一定的线程数程度后,即使再增加CPU也无法提高性能,例如Windows Server 2003,大约是1500个左右的线程数就快到极限了(线程堆栈设定为1M),如果设定线程堆栈为2M,还达不到1500个线程总数;
  • 线程能够提高的总性能有限,而且线程多了之后,线程本身的调度也是一个麻烦事儿,需要消耗较多的CPU

【总结】
在开发中,最好是多进程和多线程结合,即根据实际的需要,每个CPU开启一个子进程,这个子进程开启多线程可以为若干同类型的数据进行处理。当然你也可以利用多线程+多CPU+轮询方式来解决问题。方法和手段是多样的,关键是自己看起来实现方便有能够满足要求,代价也合适。

3. 并发 和 并行

并发和并行的比喻

并发(concurrency),指同一时刻只能有一条指令执行,多个线程的对应的指令被快速轮换地执行,线程 / 任务之间会互相切换。

  • 处理器先执行线程 A 的指令一段时间,再执行线程 B 的指令一段时间,再切回到线程 A,快速轮换地执行。
  • 处理器切换过程中会进行上下文的切换操作,进行多个线程之间切换和执行,这个切换过程非常快,使得在宏观上看起来多个线程在同时运行。
  • 每个线程的执行会占用这个处理器一个时间片段,同一时刻,其实只有一个线程在执行。

并行(parallel) 指同一时刻,有多条指令在多个处理器上同时执行。

  • 不论是从宏观上还是微观上,多个线程都是在同一时刻一起执行的。
  • 并行只能在多处理器系统中存在,如果只有一个核就不可能实现并行。

【区别】并发在单处理器和多处理器系统中都是可以存在的,一个核就可以实现并发。
【注意】具体是并发还是并行取决于操作系统的调度。

参考链接:

  • (知乎)线程和进程的区别是什么?
  • 进程与线程的一个简单解释
  • Python:多进程和多线程
  • Python多线程与多进程
  • 进程、线程,cpu核数的关系
  相关解决方案