python 多线程多进程多协程

本文详细探讨了Python中多线程、多进程和协程的概念与应用,对比了它们之间的优劣,阐述了如何在不同场景下选择最适合的并发模式,以提升程序效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

python 多线程多进程多协程

进程:一个运行的程序(代码)就是一个进程,没有运行的代码叫程序
进程是系统资源分配的最小单位;进程有自己独立的内存空间(数据不共享,开销大)
线程:调度执行的最小单位,也叫执行路径,不能独立存在,依赖进程
存在一个进程至少有一个线程(主线程);
多个线程共享内存(数据共享,共享全局变量),提高程序运行效率
协成:一种用户态的轻量级线程,协成的调度完全由用户控制;
协成拥有自己的寄存器,上下文和栈;
协成调度切换时,将寄存器上下文和栈保存到其他地方;
切回来的时候,回复先前保存的寄存器上下文和栈;
直接操作栈基本没有内核操作的开销,不加锁访问全局变量,上下文切换很快;

多线程竞争:线程非独立,同一个进程里线程数据共享,当各个线程访问数据资源时会出现竞争状态;
数据几乎同步会被多个线程占用,造成数据混乱,即所谓的线程不安全;
解决多线程竞争问题------锁
锁的好处:确保了某段关键代码(共享数据资源)只能由一个线程从头到尾完整的执行,
能解决多线程资源竞争下的原子操作问题
锁的坏处:阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率大大降低
锁的致命问题:死锁

多进程:
在Python中,存在一个跨平台的包mutiprocessing,通过引入包中的Process类,
就可以创建多进程程序了,可以创建一个进程p=Process(target=func,args=(*,)),
然后利用p.start()及p.join()来执行了。以上的join()方法可以等待子进程结束后才往下执行,
通常用于进程间同步;
可以用进程池的方式,例如p=Pool(n),然后p.apply_async(func,args),
这里可以使用n种不同的参数传入,建立不同的进程。用这种方式时,
在调用join()方法前,要先调用close()方法,使得不能再添加新进程;

多线程:
在多线程编程中,有一个最大的问题就在于进程内的资源被各个线程所共享,
进程内任何变量都可以被任何一个线程修改,因此,线程之间若去修改同一个变量,
则可能导致程序Bug。所以,引入了锁机制;
当某个线程去修改某个变量时,可以在变量所在的方法内加一把锁,
使得其他线程不能同时执行该方法,只有释放了锁后,
其他线程才能去获得锁并获得修改权。
创建一个锁是通过lock=threading.Lock()来实现的,可以使用try···finally···语句,
在try之前使用lock.acquire()获得锁,然后在try语句里面修改变量,
然后在finally语句里加lock.release()来保证锁一定被释放,避免成为一个死锁。

多线程多进程区别与联系
多进程的优点是稳定性好,一个子进程崩溃了,不会影响主进程以及其余进程。
但是缺点是创建进程的代价非常大,因为操作系统要给每个进程分配固定的资源,
并且,操作系统对进程的总数会有一定的限制,若进程过多,
操作系统调度都会存在问题,会造成假死状态。

多线程优点是效率较高一些,但是致命的缺点是任何一个线程崩溃都可能造成整个进程的崩溃,
因为它们共享了进程的内存资源池。 对于任务数来说,无论是多进程或者多线程,都不能太多。
因为操作系统在切换任务时,会有一系列的保护现场措施,这要花费相当的系统资源,
若任务过多,则大部分资源都被用做干这些了,结果就是所有任务都做不好,
所以操作系统会限制进程的数量。 另外,考虑计算密集型及IO密集型应用程序。
对于计算密集型,多任务势必造成资源浪费。对于IO密集型,
因为IO速度远低于CPU计算速度,所以使用多任务方式可以大大增大程序运行效率。

协程,又称微线程 英文名Coroutine。

协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)
。 为啥说它是一个执行单元,因为它自带CPU上下文。这样只要在合适的时机,
我们可以把一个协程 切换到另一个协程。
只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的。

在实现多任务时, 线程切换从系统层面远不止保存和恢复 CPU上下文这么简单。
操作系统为了程序运行的高效性每个线程都有自己缓存Cache等等数据,
操作系统还会帮你做这些数据的恢复操作。 所以线程的切换非常耗性能。
但是协程的切换只是单纯的操作CPU的上下文,所以一秒钟切换个上百万次系统都抗的住。

协程 -> 微线程 在不开辟线程的情况下 完成多个任务"交替执行" 网络爬虫

协程是一个特殊的生成器

yield 返回值 生成器

yield 协程(没返回值就是协程)

greenlet已经实现了协程,但是这个还的人工切换,是不是觉得太麻烦了,不要捉急,
python还有一个比greenlet更强大的并且能够自动切换任务的模块gevent

其原理是当一个greenlet遇到IO(指的是input output 输入输出,比如网络、文件操作等)操作时,
比如访问网络,就自动切换到其他的greenlet,
等到IO操作完成,再在适当的时候切换回来继续执行

由于IO操作非常耗时,经常使程序处于等待状态,
有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO

简单总结

进程是资源分配的单位

线程是操作系统调度的单位

进程切换需要的资源很最大,效率很低

线程切换需要的资源一般,效率一般(当然了在不考虑GIL的情况下)

协程切换任务资源很小,效率高

多进程、多线程根据cpu核数不一样可能是并行的,但是协程是在一个线程中 所以是并发

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值