为什么在python里推荐使用多进程而不是多线程

Python多线程下,每个线程的执行方式为:1、获取GIL2并执行代码,直到sleep或者python虚拟机挂起为止。
3.释放GIL表明,如果一个线程想要执行,必须首先获得GIL。
我们可以把GIL看成是“通行证”,在一个python进程中,只有一个GIL。
无法获得通行证的线程不允许进入CPU执行。
在Python2.x中,GIL的释放逻辑是当前线程遇到IO操作或者ticks计数达到100(ticks可以看做是Python本身的一个计数器,专门用于GIL,每次释放后都会重置为零)这个计数可以通过sys.setcheckinterval来调整)并释放。
每次释放GIL锁时,线程都会竞争锁并切换线程,从而消耗资源。
并且由于GIL锁的存在,Python中的一个进程同时只能执行一个线程(获得GIL的线程才能执行)。
这就是Python在多核CPU上多线程效率不高的原因。
那么python的多线程就完全没有用了吗?这里我们讨论分类:1.CPU密集型代码(各种循环处理、计数等)。
这种情况下,由于计算工作量很大,tick计数很快就会达到阈值,然后触发GIL的释放和释放。
又是竞争(多线程之间来回切换肯定会消耗资源),所以python下的多线程对于CPU密集型代码并不友好。
2、对于IO密集型代码(文件处理、网络爬虫等),多线程可以有效提高效率(单线程下会有IO等待IO操作,造成不必要的时间浪费,开启多线程)线程化可以有效提高效率,当线程A等待时,自动切换到线程B,不浪费CPU资源,从而提高程序执行效率)。
因此,python的多线程对于IO密集型代码更加友好。
在Python3.存在一个线程能够执行的问题,所以效率还是不理想。
请注意:多核多线程比单核多线程差。
原因是在单核多线程下,每次释放GIL时,唤醒的线程都可以获得GIL锁,因此可以无缝执行。
但多核下,CPU0被释放。
GIL之后,其他CPU上的线程会竞争,但是GIL可能会立即被CPU0获得,导致其他几个CPU上被唤醒的线程会被唤醒等待切换时间,然后进入待调度状态。
这会导致线程抖动并导致效率降低。
回到最初的问题:我们经常听到老手说:“如果你想在Python中充分利用多核CPU,就使用多进程”。
原因是什么?原因是:每个进程都有自己独立的GIL,互不干扰,这样才能真正意义上的并行执行。
因此,在python中,多进程的执行效率要优于多线程(仅针对多核CPU)。
所以这里得出结论:多核下,如果想要并行提高效率,比较常见的方法就是使用多进程,这样可以有效提高执行效率。

Python多线程是什么意思?

简单来说,作为唯一可以支持多线程的解释性语言(Perl的多线程被禁用,而PHP没有多线程),Python的多线程被破坏了,任何时候都只有一个Python解释器在解释它。
.Python字节码。
更新:正如评论中指出的,Ruby也有线程支持,并且至少RubyMRI有一个GIL。
如果您的代码是CPU密集型的,则具有多个线程的代码可能会线性运行。
所以这种情况下多线程就没用了,而且由于上下文切换,效率可能还不如单线程。
但是,如果你的代码是IO密集型的,多线程可以大大提高效率。
例如,当你构建一个爬虫时(我不明白为什么Python总是与爬虫联系在一起......但我只能想到这个例子......)爬虫主要是在等待套接字返回数据。

此时,C代码已经releaseGIL了,所以最终的结果就是一个线程等待IO的同时,其他线程可以继续运行。
另一方面,您不应该使用Python编写CPU密集型代码...效率就在那里...如果您确实需要在CPU密集型代码中使用并发性,请使用多处理库。
该库基于多进程实现了类多线程的API接口,并部分使用pickles实现了变量共享。
还有一件事,如果你不知道你的代码是CPU密集型还是IO密集型,还有一种方法。
多处理模块有一个虚拟子模块,用于实现多线程多处理API。
要实现concurrencyfrommultiprocessingimportPool,假设您使用的是使用多个进程的多处理池。
按如下方式更改此代码将导致concurrencyfrommultiprocessing.dummyimportPool的多线程实现:采取哪种方法更快。
更新:我刚刚发现Concurrent.futures其中包括ThreadPoolExecutor和ProcessPoolExecutor。
这比多处理更简单。