进程与线程
进程是计算机中数据分配、资源调度的最小单元,一个程序可以包含多个进程,至少也会有一个主进程。一个进程内的所有线程共享该进程的资源。
线程是计算机中的最小执行单元,一个进程可以包含多个线程,但是至少会有一个主线程,由CPU调度完成具体的数据运算。写的程序如果没有手动开启多线程,则全部都是单线程程序。
并行与并发
并行指在同一时刻,有多条指令在多个处理器上同时执行。所以无论从微观还是从宏观来看,二者都是一起执行的,是指两个或者多个事件在同一时刻发生。并行的关键是你有同时处理多个任务的能力。 在Python中,多进程才是并行。
并发指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行,是指两个或多个事件在同一时间间隔发生。并发的关键是你有处理多个任务的能力,但不一定要同时。
在Python中,多线程指的便是并发。
GIL锁
GIL即CPython的全局解释器锁(Global Interpreter Lock)。首先需要明确的一点是GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念,JPython就没有GIL。
解决多线程之间数据完整性和状态同步,即数据安全,最简单方法就是加锁。于是CPython才出现了GIL这把超级大锁。因为大量Python库代码的开发者已经重度依赖GIL,所以说这把锁已经变成了Python的一个比较严重的历史遗留问题。正因为这把锁,导致Python几乎等于一个单线程的程序。
GIL会阻止多个线程运行同一代码,确保由所有进程共享的内存不会中断,但这样做存在性能瓶颈。
I\O密集型(文件处理、网络爬虫)代码开启多线程则是一个并发执行的过程,由于会进行I/O等待,并发也就会充分利用等待时间,于是可以做到提高效率。
多线程遇到CPU密集型(循环、计算)代码时,单线程会比多线程的快。因为计算量太大,会触发GIL的释放与在竞争,多个线程间来回切换也会过度损耗资源。
因为GIL的存在,只有IO密集型场景下的多线程会得到较好的性能,而在CPU密集型(计算密集型)或者高并发场景下,推荐使用多进程效率会更快。毕竟每个进程有各自独立的GIL,互不干扰,即真正意义上的并行执行。但多进程占用的资源更多,所以仍然需要酌情考虑。
更多关于Python的GIL锁的内容可参考下列链接的文章: