浅谈python中的多线程和多进程

前言

在开始谈python多线程和多进程之前,先介绍一下并行、并发等日常开发中常见的的执行方式
并发:是指同一个时间段内,有多个程序在同一个CPU上运行,但是在任意时刻只有一个程序在CPU上运行

  • 并行:指任意时刻点上,有多个程序同时运行在多个CPU上
  • 同步:指代码调用IO操作时,必须等待IO操作完成才能返回的调用方式
  • 异步:指代码调用IO操作时,不必等待IO操作完成就返回的调用方式,多线程就是典型的异步操作
  • 阻塞:指调用函数时,当前线程被挂起
  • 非阻塞:指调用函数时,当前线程不会被挂起,而是立即返回

Unix下五种IO模型:
阻塞式、非阻塞、IO复用、信号驱动、异步IO
在这里插入图片描述

python中多线程

1、什么是线程?

进程是资源费配的单位,线程是CPU调度运行的基本单位,即使是多个进程,也是按照多个线程去运行调度的。

  • 拥有四个线程的进程比一个线程的进程会占有更多的CPU时间片,达到加速程序的效果。
  • 四个线程的进程运行在四核的CPU机器上,跟四个单线程进程同样是核的利用率达到100%

假定每个线程运行代码都是纯CPU计算过程,多线程情况下是没用。因为在python多进程中,只有一个线程正在被执行,下面就需要介绍python中的GIL

2、GIL

GIL(Global Interpreter Lock)全局解释锁,是Cpython解释器上的一把互斥锁。

  • 不能利用多线程实现多核任务(并行),解释器内部不支持多个线程同时解释执行。
  • 对于密集型任务,不饿能利用多核,效率不高,不过在多进程下可以利用多核
  • 若有IO阻塞,会在阻塞前提前释放GIL锁,使下一个线程获得GIL被正常调度运行

在Python多线程下,每个线程的执行方式:
1.获取GIL
2.执行代码直到sleep或者是python虚拟机将其挂起。
3.释放GIL

3、python多线线程并没有起到并行计算的作用

python线程的确是封装在底层的操作系统的线程,并且python线程也完全收到操作系统的系统管理,但是由于解析器的C语言实现部分在完全并行执行时并不是线程安全的。
因此解释器被一个全局解释器锁保护着,能确保任何时刻只能一个python线程执行,这样导致python多线程斌不能利用多核CPU优势,使用多线程的计算密集型程序只会在单个CPU上面运行

4、即使有GIL,也要考虑线程安全的问题

因为在高级语言中,一条语句在CPU执行中,实际上是多条语句,并且由于python多线程是交替运行的,所以运行过程中,会出现共享资源安全问题,所以python中多线程还是要加锁的

5、为什么频繁的线程切换开销很大

系统内核调度的对象是线程,因为线程是调度的基本单元(进程是资源拥有的基本单元)
而线程的调度只有拥有最高权限的内核空间才可以完成,所以线程的切换涉及到用户空间和内核空间的切换,也就是特权模式切换
然后需要操作系统调度模块完成线程调度(taskstruct),而且除了基本的 CPU 上下文,还有线程私有的栈和寄存器等

6、python下想要充分利用多核CPU,就用多进程”

原因是:每个进程有各自独立的GIL,互不干扰,这样就可以真正意义上的并行执行,所以在python中,多进程的执行效率优于多线程(仅仅针对多核CPU而言)。

结论

  • 多核下,想做并行提升效率,比较通用的方法是使用多进程,能够有效提高执行效率
  • IO密集型代码(文件处理、网络爬虫等),多线程能够有效提升效率(单线程下有IO操作会进行IO等待,造成不必要的时间浪费,而开启多线程能在线程A等待时,自动切换到线程B,可以不浪费CPU的资源,从而能提升程序执行效率)。所以python的多线程对IO密集型代码比较友好
  • CPU密集型代码(各种循环处理、计数等等),在这种情况下,ticks计数很快就会达到阈值,然后触发GIL的释放与再竞争(多个线程来回切换当然是需要消耗资源的),所以python的多线程对CPU密集型代码并不友好。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值