前言
最近在写一些脚本的时候,觉得还是太慢吧,而且有时候在使用线程和进程的时候不免会出现一些匪夷所思的问题,所以就诞生了这么一个系列,我会写一些小栗子代码,带大家一起去学习一下 Python 的线程和进程,以便大家在以后的学习生活中不那么的迷茫!然后的话就是说两点,第一点就是本系列是从线程出发去讲的,只有明白了线程是咋回事,那么去使用进程的时候就易如反掌了,所以进程的章节不会包含太多,第二点就是,我认为现阶段大家听到的协程对开发一些安全工具的用处不大,所以这个系列不会讲,OK 那就开始吧
术语概念解析
这些术语可能是你会遇到的,术语解析的顺序将按照从简单到复杂依次进行
并发
单核,多个任务交替进行完成; 简单理解:一个人(相当于一个核)要开始做一顿饭 ,那么他得买菜,切菜,炒菜,焖大米等等,这个人完成整个做饭的过程,就是为了执行完成多个任务,然后再看这个比较官方的说法
在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状,这种方式我们称之为并发(Concurrent)
并行
多核,多个 CPU 同时执行任务完成; 简单理解:多个人(相当于多个核)要开始做一顿饭,那么上述的那些工作就可以交给不同的人去做,有人洗菜,有人煮饭,有人切菜,有人炒菜;提高做饭的效率,多个 CPU 同时协助执行提高效率,同样的再来看以下的说法
当系统有一个以上CPU时,则线程的操作有可能非并发,当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)
进程
进程的概念:一个正在打开运行中的程序就称为进程,通俗理解就相当于 QQ,微信运行起来的程序,打开后就变成了一个各自独立的进程,任务管理器中可查看,一个运行起来的程序至少有一个进程,而多进程意思就是说,多个运行起来的程序就是一个多进程
单线程 / 多线程
线程是程序执行的最小单位,线程是依附于进程中执行的,一个程序默认最少都会有一个线程 简单理解: 你有一个想接满水的大盆,(线程好比水龙头)你开一个水龙头接水,和开多个水龙头接水,效率远远不一样,就像打开 QQ 后想和多个人聊天,打开多个聊天窗口(多个线程)的聊天一样,实现多任务的同时节省了资源
这里先提一嘴吧,Python 的多线程和其他语言还是有很大区别的,原则上讲是假的多线程。下面的解释引自知乎:
Python 代码的执行由 Python 虚拟机(解释器)来控制。Python 在设计之初就考虑要在主循环中,同时只有一个线程在执行,就像单 CPU 的系统中运行多个进程那样,内存中可以存放多个程序,但任意时刻,只有一个程序在 CPU 中运行。同样地,虽然 Python 解释器可以运行多个线程,只有一个线程在解释器中运行。对 Python 虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同时只有一个线程在运行。在多线程环境中,Python 虚拟机按照以下方式执行。
1.设置 GIL。
2.切换到一个线程去执行。
3.运行。
4.把线程设置为睡眠状态。
5.解锁 GIL。
6.再次重复以上步骤。
对所有面向 I/O 的(会调用内建的操作系统 C 代码的)程序来说,GIL 会在这个 I/O 调用之前被释放,以允许其他线程在这个线程等待 I/O 的时候运行。如果某线程并未使用很多 I/O 操作,它会在自己的时间片内一直占用处理器和 GIL。也就是说,I/O 密集型的 Python 程序比计算密集型的 Python 程序更能充分利用多线程的好处。
小 Tip
现在不要刻板的认为,线程就是并发的,进程就是并行的,这么说吧
-
线程具有并发性,因为多个线程可以在同一时间段内交替执行任务
-
线程具有并行性,因为多个线程可以在同一时间段内同时执行任务(线程在不同核上)
-
进程具有并发性,因为多个进程可以在同一时间段内交替执行任务
-
进程具有并行性,因为多个进程可以在同一时间段内同时执行任务
但是呢,在 python 里面,由于 GIL 的存在,我们一般的话就线程并发,进程并行了
-
线程更适合处理并发任务:由于线程具有轻量级和共享资源的特点,它们更适合用于处理并发任务。多个线程可以在同一时间段内交替执行,从而提高程序的效率和性能
-
进程更适合处理并行任务:由于进程具有独立地址空间和独立资源的特点,它们更适合用于处理并行任务。多个进程可以在同一时间段内同时执行,从而提高程序的并行能力
怎样去选择多线程和多进程
要想去分清啥时候使用多线程,啥时候使用多进程,咱们还是得先弄清楚这两个概念,一个是 CPU 密集型计算,IO 密集型计算
CPU 密集型
CPU 密集型也可以叫做计算密集型,是指的 I/O 可以在很短的时间就可以完成,CPU 需要大量的计算和处理,特点就是 CPU 的占用率特别高,比如:压缩解压缩,计算阶乘,加密解密,正则表达式搜索等等
IO 密集型
IO 密集型指的是系统运作大部分的状况是 CPU 在 I/O(硬盘/内存/网络网卡)的读/写操作,CPU 占用率较低,例如:处理文件的程序,网络爬虫。读写数据库
选择
所以这么看的话,多进程就适用于 CPU 密集型计算,而多线程则适用于 IO 密集型计算,这里再举个例子,比如爬取数据的时候,首先 CPU 要解析程序,然后调用网卡与目标网站建立连接,如果不用多线程或者是多进程的话,在面对大量网站 url 的时候,那就只能从上到下依次执行;而用了多线程的话,那么网卡工作的时候 CPU 就是闲下来的,那么利用多线程就可以去让 CPU 紧接着就处理解析下一段程序,就是把时间用的更紧凑了
然后这节就说到这里,接着会带大家一起去开始学习多线程