最近出去面试,问python语言特性的时候GIL和gevent被问的挺多的。发现自己对GIL的认知仅仅限于知道这个概念,觉得这次好好的查查资料,把GIL搞个清楚。做到知其然知其所以然(ps:对待技术的态度很重要,发现自己在学校的时候有种心态就是什么技术浅尝辄止不了解原理,开始工作了还带着这种心态是非常危险的,在学校的时候写写小demo,运行出错了就出错了,效率低点就低一点,但是在公司就不一样了,对自己的程序运行结果没有一个了解,半知半解的写个东西发到线上出了问题可能影响的就是几百几千万用户)。
整理了下需要知道的有这几个方面:
1. GIL是什么?
先来看一下python官网给出的定义
In CPython, the global interpreter lock, or GIL, is a mutex that protects access to Python objects, preventing multiple threads from executing Python bytecodes at once. This lock is necessary mainly because CPython's memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)
这么一大串英文有几个关键字。CPython,mutex(互斥),multiple threads(多线程),bytecodes(字节码)。thread-safe(线程安全)
所以连起来大概意思就是全局解释器锁是CPython实现中的概念,是一个保护互斥python对象的互斥机制,防止多线程同时运行一个python的字节码。需要这种锁是因为Cpython的内存管理不是线程安全的。
查了下python源码指南,GIL这一章说的是因为python里任何类型都是对象,所以很多操作都要加锁的话实现比较麻烦,所以作者就偷了个懒,加了GIL来保证字节码级别的线程安全(这里还是不太清楚)
2. GIL带来了什么问题?
单核CPU的情况下,因为同一时间只可能有一个时间片执行。所以没有什么问题。但是在多核的情况下,其它的线程没有办法并行的去执行。处在等待锁的状态,使得没有办法利用多核的优势。并且因为一个线程释放锁到唤醒其他线程后锁继续被这个线程取得导致实际执行时间比单线程还要多。见文章(http://python.jobbole.com/81822/)
总结:需要利用多核的时候利用多进程
3. 如何解决?
1. multiprocess(进程调度开销比线程大,所以应该不如其他语言的多线程)
2. 需要异步处理的情况使用协程:
gevent(协程的方式处理多任务,monkey_patch可能有坑,Guidovanrossum说patch-and-pray)协程还是不能利用多核,适合IO密集型任务。asyncio(python3)
网友评论