110、Python并发编程:利用os模块轻松实现多进程编程

南宫理的日志录 2024-12-03 07:48:52
引言

多线程编程的相关介绍告一段落,今天开始介绍关于多进程编程的内容。

本文的主要内容有:

1、多线程与多进程的比较

2、通过os模块简单演示多进程

多线程与多进程的比较

通过前面的文章,相信能够对多线程编程有一个相对完整、清晰的理解。在真正进入多进程编程的内容介绍之前,首先来比较一下,多线程和多进程,通过类比,希望能够对多进程有个更加全局性的认知,也加深一下对多线程内容的掌握。

接下来,将分别从执行效率、资源开销、编程复杂性及适用场景方面,对两者进行比较。

1、执行效率

通常来说,多线程的优点在于线程的切换相对轻量级,多线程复用同一个进程的内存资源,包括堆栈等,创建、销毁、切换上下文,相对开销较小。因此,在CPU密集型任务中,多线程的执行效率较高。

但是,在Python中,由于全局解释器锁(GIL)的存在,对于CPU密集型任务,多线程并不能实现真正的并行执行,可能会导致性能受限。反而是IO密集型任务,Python中的多线程更能利用IO等待时间,发挥并行的优势。

多进程中,每个进程有自己的内存空间和资源,能够实现真正的并行,特别是在多核CPU上,更加适用于CPU密集型任务。但是,进程的上下文切换,可能会导致效率的降低。

2、资源开销

线程之间,由于共享内存和资源,因此在频繁通信的场景中,线程资源的开销相对较小。但是,由于资源的共享,也引入了一致性和竞争问题,需要小心进行同步的管理。

多进程中,每个进程拥有独立的内存空间,进程间不会直接影响,安全性更高,但是,进程间通信的资源开销较大,且进程上下文切换也会导致更多的资源开销。

3、编程复杂性

多线程编程相对容易实现,代码结构也比较简洁。但是,由于共享内存和竞争条件,可能会引入复杂性,需要更多地考虑线程安全和同步的问题。

多进程中,每个进程相互独立,数据的隔离使得编程更加安全,减少了多线程中线程安全问题的复杂性。但是,跨进程的通信协作,也会引入新的复杂性。

4、适用场景

通常来说,多线程更适合IO密集型任务,以及大量的短时任务的并发场景,因为其上下文切换、创建、销毁资源开销较小。但是,Python中,GIL的存在,导致多线程不太适合CPU密集型任务。

多进程编程,特别适合CPU密集型任务,比如大数据处理、图像处理等。多进程能够充分利用多核CPU的优势,真正实现并行处理。但是,如果是大批量短时任务,涉及到频繁的进程创建、销毁、上下文切换,可能反而会导致执行效率的降低。

通过os模块简单演示多进程

简单对比了多线程和多进程的各个维度下的优缺点,接下来,通过Python中的os模块,来简单演示一下多进程。

首先简单介绍一下os模块中,关于进程管理的常用方法:

1、os.fork()函数

创建子进程,调用该函数后,当前进程将被复制,整个进程的状态、堆栈数据、代码都会被复制到子进程中。

在父进程中,会返回子进程的PID,在子进程中会返回0。

2、os.exec*家族函数

用指定的程序替换当前进程的映像,比如os.execvp()、os.execv()等。执行完成后会返回到调用的程序中,当前进程被新的程序替换。

3、os.wait()

使当前进程挂起,直到一个子进程终止,返回值包含子进程的PID以及其退出状态。通常在父进程中调用,用于等待子进程结束,防止僵尸进程。

4、os.kill(pid, sig)

向指定PID的进程发送一个信号,可以用来终止或者控制进程的行为,相关的信号,可以通过signal模块查看:

5、os.getpid()和os.getppid()

分别用于获取当先进程的PID和当前进程的父进程的PID。

接下来,通过代码简单演示一下多进程的执行效果。

需要首先说明的是,os模块中的相关方法和组件,有些可能是基于Linux内核的调用。以下代码,在Linux或者mac可以正常运行,但是在Windows上可能会出现异常。

执行结果:

从执行结果可以看到:

1)从os.fork()这一行开始,后续的代码会同样在子进程中执行一遍,所以,以下的代码会执行两遍(主进程和子进程)。

2)主进程中通过os.wait()将等待子进程结束才继续向下执行。

3)os.execlp()的函数调用,导致主进程和子进程的映像都被替换为ls的执行了。所以,之后的代码不会被执行了。

总结

本文通过对多线程和多进程的比较,一方面对多线程的内容做了个梳理总结,另一方面也对多进程的内容,做了一个全局性的引入。最后,通过os模块中相关进程管理的函数,简单演示了多进程。

以上就是本文的全部内容,感谢您的拨冗阅读。

0 阅读:5

南宫理的日志录

简介:深耕IT科技,探索技术与人文的交集