Python3中多进程和多线程的理论相关

作者:艾胖胖胖
链接:https://www.jianshu.com/p/b07f9f83142e
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

一、多任务

之所以需要使用多进程或者是多线程,归根结底就是为了进行多任务的处理。那么,多核CPU实现多任务原理和单核CPU的多任务原理是什么呢。

单核CPU的多任务原理

操作系统轮流让各个任务交替执行。比如:QQ执行2毫秒,微信执行2毫秒…任务不断反复切换,但又因为CPU调度执行速度太快了,导致我们感觉就是所有的任务都在同时执行。

多核CPU实现多任务原理

真正的多任务只能在多核CPU上实现,但是由于任务数量远远多于CPU的核心数量。所以,操作系统也会自动把很多任务轮流调度到每个核心上执行。

一般情况下任务数往往大于你的CPU核心数,所以会出现一颗CPU执行多个任务的情况。而这,又引出了并发和并行的概念

并发和并行

因为CPU的核心与任务数的不同。所以又出现了并发和并行的概念。

  • 并发:指的是任务数多余cpu核心数(你总有一颗CPU核心不止运行一个任务),所以只能通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(因为切换任务的速度相当快,看上去一起执行而已。可以借助单核CPU的多任务原理来进行理解)

  • 并行:指的是任务数小于等于cpu核心数,即任务真的是一起执行的。效率最高

实现多任务的几种方式:
  1. 多进程模式
  2. 多线程模式
  3. 协程模式
  4. 多进程+多线程模式

二、进程和线程

进程

对于操作系统而言,一个任务就是一个进程。进程是系统中程序执行和资源分配的基本单位,每个资源都有自己的数据段、代码段和堆栈段

线程

线程是操作系统能够进行运算调度的最小单位(程序执行流的最小单元)。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

进程和线程的区别
  1. 线程共享内存空间;进程的内存是独立的
  2. 同一个进程的线程之间可以直接交流;两个进程想通信,必须通过一个中间代理来实现
  3. 创建新线程很简单; 创建新进程需要对其父进程进行一次克隆
  4. 一个线程可以控制和操作同一进程里的其他线程;但是进程只能操作子进程
  5. 改变主线程(如优先权),可能会影响其它线程;改变父进程,不影响子进程
多进程和多线程的优缺点
  • 多进程
    缺点:密集CPU任务,需要充分使用多核CPU资源(服务器,大量的并行计算)的时候,用多进程。

缺陷:多个进程之间通信成本高,切换开销大。

  • 多线程
    优点:密集I/O任务(网络I/O,磁盘I/O,数据库I/O)使用多线程合适。

缺陷:同一个时间切片只能运行一个线程,不能做到高并行,但是可以做到高并发。

线程在Python里是鸡肋的说法

首先来介绍一下GIL:GIL的全称是Global Interpreter Lock(全局解释器锁),来源是python设计之初的考虑,为了数据安全所做的决定。一个线程想要执行,必须先拿到GIL。

在Python多线程下,每个线程的执行方式:

  • 获取GIL
    执行代码直到sleep或者是python虚拟机将其挂起。
  • 释放GIL
    在Python2.x里,GIL的释放逻辑是当前线程遇见IO操作或者ticks计数达到100(ticks可以看作是Python自身的一个计数器,专门做用于GIL,每次释放后归零,这个计数可以通过 sys.setcheckinterval 来调整),进行释放。

而每次释放GIL锁,线程进行锁竞争、切换线程,会消耗资源。并且由于GIL锁存在,python里一个进程永远只能同时执行一个线程(拿到GIL的线程才能执行),这就是为什么在多核CPU上,python的多线程效率并不高。

在一个python进程中,GIL只有一个。拿不到通行证的线程,就不允许进入CPU执行。所以,每个CPU在同一时间只能执行一个线程。而每个进程有各自独立的GIL,所以多进程的执行效率优于多线程(仅仅针对多核CPU而言)。

存在即合理,Python的多线程还是要进行分类讨论

CPU密集型代码(各种循环处理、计数等等),在这种情况下,由于计算工作多,ticks计数很快就会达到阈值,然后触发GIL的释放与再竞争(多个线程来回切换当然是需要消耗资源的),所以python下的多线程对CPU密集型代码并不友好。

IO密集型代码(文件处理、网络爬虫等),多线程能够有效提升效率(单线程下有IO操作会进行IO等待,造成不必要的时间浪费,而开启多线程能在线程A等待时,自动切换到线程B,可以不浪费CPU的资源,从而能提升程序执行效率)。所以python的多线程对IO密集型代码比较友好。

多核多线程比单核多线程更差,原因是单核下的多线程,每次释放GIL,唤醒的那个线程都能获取到GIL锁,所以能够无缝执行,但多核下,CPU0释放GIL后,其他CPU上的线程都会进行竞争,但GIL可能会马上又被CPU0拿到,导致其他几个CPU上被唤醒后的线程会醒着等待到切换时间后又进入待调度状态,这样会造成线程颠簸(thrashing),导致效率更低。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值