Python多进程与多线程编程及GIL详解(7)

multiprocess库的出现很大程度上是为了弥补thread库因为GIL而低效的缺陷。它完整的复制了一套thread所提供的接口方便迁移。唯一的不同就是它使用了多进程而不是多线程。每个进程有自己的独立的GIL,因此也不会出现进程之间的GIL争抢。

当然multiprocess也不是万能良药。它的引入会增加程序实现时线程间数据通讯和同步的困难。就拿计数器来举例子,如果我们要多个线程累加同一个变量,对于thread来说,申明一个global变量,用thread.Lock的context包裹住三行就搞定了。而multiprocess由于进程之间无法看到对方的数据,只能通过在主线程申明一个Queue,put再get或者用share memory的方法。这个额外的实现成本使得本来就非常痛苦的多线程程序编码,变得更加痛苦了。

用其他解析器

之前也提到了既然GIL只是CPython的产物,那么其他解析器是不是更好呢?没错,像JPython和IronPython这样的解析器由于实现语言的特性,他们不需要GIL的帮助。然而由于用了Java/C#用于解析器实现,他们也失去了利用社区众多C语言模块有用特性的机会。所以这些解析器也因此一直都比较小众。毕竟功能和性能大家在初期都会选择前者,Done is better than perfect。

所以没救了么?

当然Python社区也在非常努力的不断改进GIL,甚至是尝试去除GIL。并在各个小版本中有了不少的进步。

另一个改进Reworking the GIL
– 将切换颗粒度从基于opcode计数改成基于时间片计数
– 新增线程优先级功能(高优先级线程可以迫使其他线程释放所持有的GIL锁)
– 避免最近一次释放GIL锁的线程再次被立即调度

总结

Python GIL其实是功能和性能之间权衡后的产物,它尤其存在的合理性,也有较难改变的客观因素。从本问的分析中,我们可以做以下一些简单的总结:
◦因为GIL的存在,只有IO Bound场景下得多线程会得到较好的性能
◦如果对并行计算性能较高的程序可以考虑把核心部分也成C模块,或者索性用其他语言实现
◦GIL在较长一段时间内将会继续存在,但是会不断对其进行改进

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/42bfa63a98811a58ce1cc22409e1eb77.html