0%

python | 多进程编程和多线程编程优缺点

这个老生常谈了,但是,也可以瞅瞅。

多进程编程和多钱程编程,都可以使用并行机制来提升系统的运行效率。二者的区别在于运行时所占的内存分布不同。

  • 多钱程是共用一套内存的代码块区间
  • 多进程是各用一套独立的内存区间

多线程共享内存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from threading import Thread
import os

index = 0


def loop():
global index
index += 1
print(f"{os.getpid()} {index}",flush=True)


if __name__ == '__main__':

processes = []

for i in range(3):
t = Thread(target=loop)
processes.append(t)

for i in range(3):
processes[i].start()

for i in range(3):
processes[i].join()

输出

1
2
3
27409 1
27409 2
27409 3

多进程独立内存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from multiprocessing import Process
import os

index = 0


def loop():
global index
index += 1
print(f"{os.getpid()} {index}")


if __name__ == '__main__':

processes = []

for i in range(3):
t = Process(target=loop)
processes.append(t)

for i in range(3):
processes[i].start()

for i in range(3):
processes[i].join()

输出

1
2
3
26795 1
26794 1
26796 1

多进程的优点是稳定性好,一个子进程崩溃了,不会影响主进程以及其余进程。基于这个特性,常常会用多进程来实现守护服务器的功能。

多进程编程也有不足,即创建进程的代价非常大,因为操作系统要给每个进程分配固定的资源,并且操作系统对进程的总数会有一定的限制,若进程过多,操作系统调度都会存在问题,会造成假死状态。

多线程编程的优点是效率较高一些,适用于批处理任务等功能;不足之处在于,任何一个线程崩溃都可能造成整个进程的崩溃,因为它们共享了进程的内存资源池。

既然多线程编程和多进程编程各有优缺点,因此它们分别适用于不同的场景。比如说,对于计算密集型的任务,多进程效率会更高一下;而对于IO密集型的任务(比如文件操作,网络爬虫),采用多线程编程效率更高。为什么是这样呢?

其实也不难理解。对于 IO 密集型操作,大部分消耗时间其实是等待时间,在等待时间中,Python会释放GIL供新的线程使用,实现了线程间的切换;相反对于 CPU 密集型代码,2 个 CPU 干活肯定比一个 CPU 快很多。

在大型的计算机集群系统中,通常都会将多进程程序分布运行在不同的计算机上协同工作。而每一台计算机上的进程内部,又会由多个线程来并行工作。

注意,对于任务数来说,无论是多进程编程或者多线程编程,其进程数或线程数都不能太多:

  • 对于多进程编程来说,操作系统在切换任务时,会有一系列的保护现场措施,这要花费相当多的系统资源,若任务过多,则大部分资源都被用做干这些了,结果就是所有任务都做不好;

  • 多线程编程也不是线程个数越多效率越高,通过下面的公式可以计算出线程数量最优的一个参考值。

$$ 最佳线程数量 = \frac{线程等待时间 + 线程CPU时间}{线程CPU时间} \ast {CPU 数量} $$

  • 同一时刻一个进程只能运行一个线程,无论多少个 CPU
  • 想要利用多 CPU 只能利用 「多进程」
请我喝杯咖啡吧~