python多进程、多线程、协程与异步io

本文介绍了Python中处理IO密集型任务的不同方法,从多进程、多线程到协程的概念和优势。Python2.x的协程通过yield + send实现,Python3.x引入了asyncio模块,使用yield from和async/await语法简化异步编程。Gevent库基于Greenlet实现协程,自动切换以实现并发执行。协程在单线程内切换,降低了系统开销,适合处理异步IO任务。

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

CPU密集型 VS IO密集型
我们可以把任务分为计算密集型IO密集型
        第一种计算密集型任务的特点是要进⾏⼤量的计算,消耗CPU资源,⽐如计算圆周率、对视频进⾏⾼清解码等等,全靠CPU的运算能⼒。这种计算密集型任务虽然也可以⽤多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执⾏任务的效率就越低,所以,要最⾼效地利⽤CPU,计算密集型任务同时进⾏的数量应当等于CPU的核⼼数。
        计算密集型任务由于主要消耗CPU资源,因此,代码运⾏效率⾄关重要。Python这样的脚本语⾔运⾏效率很低,完全不适合计算密集型任
。对于计算密集型任务,最好⽤C语⾔编写。
        第⼆种IO密集型,涉及到⽹络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的⼤部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)。对于IO密集型任务,任务越多,CPU效率越⾼,但也有⼀个限度。常见的⼤部分任务都是IO密集型任务,⽐如Web应⽤。
        IO密集型任务执⾏期间,99%的时间都花在IO上,花在CPU上的时间很少,因此,⽤运⾏速度极快的C语⾔替换⽤Python这样运⾏速度极低的脚本语⾔,完全⽆法提升运⾏效率。对于IO密集型任务,最合适的语⾔就是开发效率最⾼(代码量最少)的语⾔,脚本语⾔是⾸选,C语⾔最差。
        所以,python更适合I/O密集型任务(一般都是走业务流程,网络和磁盘操作比较集中)

多进程--->多线程--->协程

一、什么是进程和线程

进程是分配资源的最小单位,线程是系统调度的最小单位。

当应用程序运行时最少会开启一个进程,此时计算机会为这个进程开辟独立的内存空间,不同的进程享有不同的空间,而一个CPU在同一时刻只能够运行一个进程,其他进程处于等待状态。

一个进程内部包括一个或者多个线程,这些线程共享此进程的内存空间与资源。相当于把一个任务又细分成若干个子任务,每个线程对应一个子任务。

二、多进程和多线程

对于一个CPU来说,在同一时刻只能运行一个进程或者一个线程,而单核CPU往往是在进程或者线程间切换执行,每个进程或者线程得到一定的CPU时间,由于切换的速度很快,在我们看来是多个任务在并行执行(同一时刻多个任务在执行),但实际上是在并发执行(一段时间内多个任务在执行)。

单核CPU的并发往往涉及到进程或者线程的切换,进程的切换比线程的切换消耗更多的时间与资源。在单核CPU下,CPU密集的任务采用多进程或多线程不会提升性能,而在IO密集的任务中可以提升(IO阻塞时CPU空闲)。

而多核CPU就可以做到同时执行多个进程或者多个进程,也就是并行运算。在拥有多个CPU的情况下,往往使用多进程或者多线程的模式执行多个任务。

三、python中的多进程和多线程

1、多进程

def Test(pid):
    print("当前进程{}:{}".format(pid, os.getpid()))
    for i in range(1000000000):
        pass

if __name__ == '__main__':
    #单进程
    start = time.time()
    for i in range(2):
        Test(i)
    end = time.time()
    print((end - start))

单进程输出结果如图1:

图1

def Test(pid):
    print("当前子进程{}:{}".format(pid, os.getpid()))
    for i in range(100000000):
        pass

if __name__ == '__main__':
    #多进程
    print("父进程:{}".format(os.getpid()))
    start = time.time()
    pool = Pool(processes=2)
    pid = [i for i in range(2)]
    pool.map(Test, pid)
    pool.close()
    pool.join()
    end = time.time()
    print((end - start))

多进程输出结果如图2:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hmk1900

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值