python的多线程和多进程

      线程是cpu执行的最小单元,因此一个进程中至少有一个线程。当我们在处理任务时,是依靠线程进行的,多线程和多进程意味着要同时处理多个任务。这里“同时”只是一个粗糙的说法,严格地讲,真正在时间上同时进行的任务处理叫做并行,而cpu资源不断的在线程之间进行切换,以达到这几个任务在效果上看起来是同时进行的,这叫做并发。

      在python中,线程和进程之间最大的不同在于,多线程没法利用多核cpu资源,但是多进程可以;因为在python中,有一个东西叫做GIL,全局解释器锁,其会使得在同一个Python解释器进程中,当一个线程执行时,其他线程会挂起,因此尽管有多个cpu,但是实际上对于这个解释器进程来说,在同一时刻也相当于只有一个cpu在工作;所以如果想要充分利用多核cpu资源,就应该使用多进程,由于每个进程有自己的一个GIL,尽管一个进程之内的线程之间受自己的GIL限制,但是进程之间是不会受其他的GIL限制的。但是对于单核cpu来说,多线程对于IO型任务来说是可以提高效率的,因为多线程可以提高cpu轮转到本任务的概率,相当于多分配了cpu时间给该任务,从而可以提高效率;对于cpu密集型任务的任务来说,由于cpu在不同的cpu密集型线程之间转换会相当花费时间,所以虽然没有GIL的限制,但是也不宜进程数量过多,因为过多的进程数会导致提高cpu轮转的概率得到的cpu时间会被轮转所额外消耗的时间抵消。当然了,使用多线程和多进程不仅仅是为了提高效率,经常的,多个任务同时进行以实现特定的效果才是目的本身,这是多进程和多线程的主要目的。

      多线程可以提高IO型任务的单核运行效率,但是并无法充分利用多核cpu资源,当然多核cpu也会提高cpu轮转到多线程任务的概率,从而多分配到cpu机会,但是GIL使得多分配到的机会并没法被充分使用,即无法充分使用多核cpu资源。对于多核cpu,当我们只是为了提高任务执行效率时,如果是cpu密集型的任务,则不宜用多线程,因为全局锁的存在,多线程无法实现并行,从而无法利用剩下的cpu,也就无法提高效率;但是对于IO密集型任务,由于主要时间在于IO端,cpu占用的资源较少,这样切换起来就会很快,所以就会更快,但是比如对于多接口爬虫之类的任务,由于其是IO密集型任务,而且主要是为了不让程序受限于某一个接口的可能的意外耗时从而导致其他接口即整个程序被延迟,便可以通过利用多线程进行,让多个接口同时获取数据,从而提高整体效率。

      提高效率可以有两种方式,减少执行时间和减少阻塞时间,对于cpu密集型,重在减少执行时间,由于一个任务在同一时刻只能由一个cpu去处理,因此要提高这个任务的执行时间就需要把这个任务拆分成多个子任务,然后利用多进程去处理,从而使得在同一时刻有多个cpu可以同时处理,充分利用cpu的资源,从而减少整个任务的执行时间。若是IO密集型任务,主要是为了减少阻塞时间,则可以多拆分多任务,进行多进程切换,以减少单个任务单元的堵塞时间对整体造成的影响,即单个任务单元堵塞的同时,让其他任务还可以继续,以减少时间的浪费。

      在python中,对于单纯的计算性任务,不要用多线程,因为GIL的存在使得无法提高计算效率,但是当然对于IO型任务还是可以提高效率的;对于CPU密集型任务,如果是一个任务,我们可以通过拆分成多个任务,然后利用多进程,充分利用CPU资源,提高效率,缩短时间。

      在python中,对于多进程,有一个multiprocessing包可以实现。我们常用的是通过创建多个进程来同时执行任务,如下代码所示,导入Pool,然后用with语句创建进程池,用apply_async()方法让多个进程同时进行,异步处理,然后通过close()方法表示不再往池里添加进程,join()方法表示等待所有的进程都执行完毕,这里join()之前必须得有close()语句才行;再接下来执行print语句,然后通过with语句结束所有进程,包括之前没有被分配任务的空进程。这里往池里添加任务进程的时候,用的是列表解析,以实现将结果保存在列表中,列表中的结果可以用get()方法获取。这是一套标准的流程。

from multiprocessing import Pool

def f(x):
    return x*x

if __name__=='__main__':
    with Pool(5) as pool:
        results=[pool.apply_async(f,[i]) for i in range(5)]
        pool.close()
        pool.join()
        print('All processes are done!')

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值