python 多线程多进程多协程

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核数不一样可能是并行的,但是协程是在一个线程中 所以是并发

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值