concurrent.futures是GIL的解药吗?
我刚在查这个新功能的实现,我用的是Python 2.7,我必须安装这个。所以如果我使用它,我就可以忘记CPython中的GIL这个词了吗?
1 个回答
不,concurrent.futures
和全局解释器锁(GIL)几乎没有任何关系。
使用进程而不是线程可以解决GIL的问题。(当然,就像所有药物一样,它也有副作用,但确实有效。)
futures
模块只是提供了一种比直接使用threading
或multiprocessing
更简单的方式来安排和等待任务。而且它还有一个额外的好处,就是你可以在线程池和进程池之间切换(甚至可以切换到你自己发明的其他奇怪的东西),而不需要修改future
的代码。所以,如果你不确定你的代码是否会遇到GIL的问题,你可以先用线程来写,然后只需一行代码就能切换到使用进程,这样挺不错的。
但是,如果你使用ThreadPoolExecutor
,它会和你手动用threading
和queue
创建线程池、任务队列等时遇到的GIL问题完全一样。如果你使用ProcessPoolExecutor
,它会以相同的方式(以及相同的权衡)避免GIL的问题,就像你手动使用multiprocessing
一样。
而且PyPI包只是将concurrent.futures
模块从3.2版本简单移植到2.x(以及3.0-3.1)而已。(它并不会神奇地给你带来新的、稍微改进的3.2 GIL,或者更改进的3.3 GIL,更不用说去掉GIL了。)
我可能不该提到GIL的变化,因为这似乎只会让事情更混乱……但现在让我试着简单化一下,来澄清这个问题。
如果你只有IO密集型的工作,线程是实现并发的好方法,直到一个合理的限制。而且3.3版本确实让它们的表现更好——但对于大多数情况,2.7已经足够好了,而对于大多数不够的情况,3.3仍然不够好。如果你想处理10000个同时连接的客户,你会想用事件循环(比如twisted
、tornado
、gevent
、tulip
等)而不是线程。
如果你有任何CPU密集型的工作,线程根本无法帮助你并行处理这些工作。实际上,它们会让事情变得更糟。3.3版本虽然让这种情况稍微好一点,但仍然是个问题,你还是不应该这样做。如果你想并行处理CPU工作,你必须使用进程,而不是线程。3.3的唯一优势是futures
比multiprocessing
稍微好用一点,而且是内置的,不需要单独安装。
我并不想让你对升级到3.3感到沮丧,因为它是比2.7更好的语言实现。但更好的并发并不是你升级的理由。