python 之 进程与线程区别、GIL锁产生背景及对Python性能的影响?python的多线程是假的,为啥还用多线程

2023-11-08

一、进程与线程区别

  • 根本区别
    进程是操作系统资源分配的基本单位。每个进程都有自己独立的地址空间、数据、堆栈和状态
    线程是处理器任务调度和执行的基本单位。一个进程可以有多个线程,这些线程共享进程的地址空间和资源
  • 资源开销(内存分配)
    进程创建新的进程需要分配独立的地址空间,有较大的字节。进程间切换和通信成本相对较高
    线程间共享地址空间和资源,因此线程的创建、切换和通信相对较接近,资源消耗较少
  • 通信方式
    进程间通信相对复杂,主要方式有管道、消息队列、信号量、共享内存等
    线程间通信更简单,可以直接访问其他线程的数据(因为它们共享地址空间),主要通过锁、信号量等同步原语来协调(也可以共享变量,共享内存,共享数据库,消息队列)
  • 隔离性与安全性:
    进程间有最大的隔离性,一个进程崩溃(例如访问了内存)一般不会影响其他进程。
    线程间共享进程资源,一个线程的错误可能影响同一进程的其他线程。
  • 使用场景
    IO密集型使用线程,计算密集型使用多进程
    进程适用于相互独立,需要较高安全性和隔离性的场景。
    线程适用于需要密集通信,或共享大量资源的场景,如服务器的请求处理
  • 补充
    协程:是一种用户态的轻量级线程,协程的调度完全由用户控制。
    协程拥有自己的寄存器上下文和栈,协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。

二、什么是GIL锁?GIL对Python性能的影响

  • GIL全局解释锁
    全局解释锁: 每个线程在执行过程的过程都需要先获取GIL,确保在同一时刻只有一个线程可以执行字节码,目的是简化CPython的设计, 保证线程安全

  • 线程释放GIL锁的情況:

    1. 在I0操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执行完毕后,必须重新获取GIL
    2. Python 3.x使用计时器(执行时间达到國值后,当前线程释放GIL)或Python 2.x, tickets计t数达到100

    python使用多进程是可以利用多核的CPU资源的。
    多线程爬取比单线程性能有提升,因为遇到I0阻塞会自动释放GIL锁
    多进程适合在 CPU 密集型操作(Cpu 操作指令比较多,如位数多的浮点运算)。
    多线程适合在 IO 密集型操作(读写数据操作较多的,比如爬虫)

  • GIL全局解释锁:目的是简化CPython的设计, 保证线程安全

    1. 保护内存管理:
      GIL保证了对Python对象的访问是线程安全的。Python使用引用计数来管理内存,而更新引用计数并不是一个原子操作。假如两个线程同时修改同一个对象的引用计数,可能会导致引用计数被错误地更新,进而引发内存泄漏或错误地回收了仍在使用的对象。GIL确保了每一时刻只有一个线程在执行Python字节码,从而避免了这种竞争条件
    2. 简化设计和实现:
      通过使用GIL,CPython解释器的实现大大简化。GIL消除了多线程环境中复杂的锁管理和同步问题。没有GIL,CPython的每个数据结构都需要单独管理锁,这将增加设计和实现的复杂性

三、为啥python的多线程是假的,还用多线程

  • 为什么说Python的多线程是“假”的:
    GIL是一个全局锁,它保证一次只有一个线程执行Python字节码。在多核CPU环境中,这意味着Python的多线程不能有效利用多个CPU核心。相反,尽管有多个线程,但在任何给定的时刻,只有一个线程在执行。这使得Python的多线程对于计算密集型任务效果不佳,因为它们无法真正地执行任务。
  1. 为什么仍然使用Python的多线程
    对于I/O密集型任务(如网络通信、文件I/O等),多线程仍然是非常有效的。
    在I/O密集型任务中,线程大部分时间都在等待外部资源
    比如等待文件读取写完成或网络响应。在此期间,CPU几乎处于空闲状态。
    通过使用多线程,当一个线程等待I/O操作完成时,GIL可以被释放,其他线程可以继续执行。
    这样,多线程可以在I /O密集型应用中提高程序的总体性能和响应能力
  2. 综上所述
    尽管Python的多线程因GIL的存在而受到了一定的限制(特别是对于计算密集型任务),它仍然在某些场景下是有用和有效的。
    选择是否使用多线程,以及如何使用,取决于具体的应用场景和性能需求。

三、为啥 IO密集型使用线程,计算密集型使用多进程

3.1 I/O密集型任务:

I/O密集型任务是指系统的性能瓶颈主要出现在I/O操作上,如文件操作、网络通信等

为什么使用线程??

  1. I/O 密集型任务中,CPU 的使用并不是瓶颈,主要时间消耗在等待 I/O 操作上。在此期间,CPU 大部分时间都是空闲的。
  2. 线程的创建和思考成本很小,且所有线程共享进程的内存空间,使得线程之间的通信和数据交换成本很低。
  3. 使用线程可以使一个进程内的多个线程在等待I/O操作时可以共享同一个资源,这样当一个线程在等待I/O时,其他线程可以继续执行
3.2 计算密集型任务:

计算密集型任务是指系统的性能瓶颈主要出现在CPU计算上,即任务需要大量的CPU计算时间

为什么使用多进程??

  1. 对于计算密集型任务,多进程可以有效地利用多核CPU的优势,因为每个进程可以在一个单独的CPU核上执行。
    进程间的独立性较强,一个进程的崩溃不会影响到其他进程。
    在解释全局器锁(GIL)的存在的环境下(例如CPython),多线程程序无法有效利用多核CPU。GIL是Python的一个互斥锁,它阻止多个线程同时执行Python字节码。
    密集型任务,这可能导致程序的效率大幅度降低。多进程则参与GIL的限制,每个进程都有自己的GIL和独立的内存空间,因此可以充分利用多核CPU。

四、进程间8种通信方式详解

  1. 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常
    是指父子进程关系
  2. 消息队列通信:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载
    无格式字节流以及缓冲区大小受限等缺点
  3. 信号量:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源
    时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
  4. 信号:信号是种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
  5. 共享内存通信:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内
    存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实来实现进程间的同步和通信。
  6. socket:套接口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信
为什么爬虫使用多线程?而不是多进程
  • 多进程占用资源多,进程间通讯不方便,爬虫很少用
  • 多线程/协程 在请求数据和解析数据的时候采用多线程,大部分时间都是单线程爬虫,大部分情况采用分布式

什么是并发和并行?.同步和异步,阻塞和非阻塞的区别?

# 并发:同一时刻只能处理一个任务,但可以交替处理多个任务。(一个处理器同时处理多个任务〕
# 并行:同一时刻可以处理多个任务。(多个处理器或者是多核的处理器同时处理多个不同的任务)
# 类比:并发是一个人同时吃三个馒头,而并行是三个人同时吃三个馒头。

线程是并发,进程是并行;进程之间相互独立,是系统分配资源的最小单位,同一个线程中的所有线程共享资源。

阻塞:在执行一个操作时,不能做其他操作;
非阻塞:在执行一个操作时,能做其他操作。

阻塞和非阻塞关心的问题是:能不能做其他操作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python 之 进程与线程区别、GIL锁产生背景及对Python性能的影响?python的多线程是假的,为啥还用多线程 的相关文章

  • 如何查看Databricks中的所有数据库和表

    我想列出 Azure Databricks 中每个数据库中的所有表 所以我希望输出看起来像这样 Database Table name Database1 Table 1 Database1 Table 2 Database1 Table
  • Python:在列表理解本身中引用列表理解?

    这个想法刚刚出现在我的脑海中 假设您出于某种原因想要通过 Python 中的列表理解来获取列表的唯一元素 i if i in created comprehension else 0 for i in 1 2 1 2 3 1 2 0 0 3
  • 无法“安装”plpython3u - postgresql

    我正在尝试在 postgresql 中使用 python 语言 像这样的事情 create or replace function test a integer returns integer as if a 2 0 return even
  • 没有名为 crypto.cipher 的模块

    我现在正在尝试加密一段时间 我最近得到了这个基于 python 的密码器 名为PythonCrypter https github com jbertman PythonCrypter 我对 Python 相当陌生 当我尝试通过终端打开 C
  • Python 中的 Lanczos 插值与 2D 图像

    我尝试重新缩放 2D 图像 灰度 图像大小为 256x256 所需输出为 224x224 像素值范围从 0 到 1300 我尝试了两种使用 Lanczos 插值来重新调整它们的方法 首先使用PIL图像 import numpy as np
  • SQLAlchemy 通过关联对象声明式多对多自连接

    我有一个用户表和一个朋友表 它将用户映射到其他用户 因为每个用户可以有很多朋友 这个关系显然是对称的 如果用户A是用户B的朋友 那么用户B也是用户A的朋友 我只存储这个关系一次 除了两个用户 ID 之外 Friends 表还有其他字段 因此
  • Django:按钮链接

    我是一名 Django 新手用户 尝试创建一个按钮 单击该按钮会链接到我网站中的另一个页面 我尝试了一些不同的例子 但似乎没有一个对我有用 举个例子 为什么这不起作用
  • PyUSB 1.0:NotImplementedError:此平台不支持或未实现操作

    我刚刚开始使用 pyusb 基本上我正在玩示例代码here https github com walac pyusb blob master docs tutorial rst 我使用的是 Windows 7 64 位 并从以下地址下载 z
  • 如何从网页中嵌入的 Tableau 图表中抓取工具提示值

    我试图弄清楚是否有一种方法以及如何使用 python 从网页中的 Tableau 嵌入图形中抓取工具提示值 以下是当用户将鼠标悬停在条形上时带有工具提示的图表示例 我从要从中抓取的原始网页中获取了此网址 https covid19 colo
  • 测试 python Counter 是否包含在另一个 Counter 中

    如何测试是否是pythonCounter https docs python org 2 library collections html collections Counter is 包含在另一个中使用以下定义 柜台a包含在计数器中b当且
  • 以编程方式停止Python脚本的执行? [复制]

    这个问题在这里已经有答案了 是否可以使用命令在任意行停止执行 python 脚本 Like some code quit quit at this point some more code that s not executed sys e
  • 添加不同形状的 numpy 数组

    我想添加两个不同形状的 numpy 数组 但不进行广播 而是将 缺失 值视为零 可能最简单的例子是 1 2 3 2 gt 3 2 3 or 1 2 3 2 1 gt 3 2 3 1 0 0 我事先不知道形状 我正在弄乱每个 np shape
  • python获取上传/下载速度

    我想在我的计算机上监控上传和下载速度 一个名为 conky 的程序已经在 conky conf 中执行了以下操作 Connection quality alignr wireless link qual perc wlan0 downspe
  • 向 Altair 图表添加背景实心填充

    I like Altair a lot for making graphs in Python As a tribute I wanted to regenerate the Economist graph s in Mistakes we
  • 如何在seaborn displot中使用hist_kws

    我想在同一图中用不同的颜色绘制直方图和 kde 线 我想为直方图设置绿色 为 kde 线设置蓝色 我设法弄清楚使用 line kws 来更改 kde 线条颜色 但 hist kws 不适用于显示 我尝试过使用 histplot 但我无法为
  • 每个 X 具有多个 Y 值的 Python 散点图

    我正在尝试使用 Python 创建一个散点图 其中包含两个 X 类别 cat1 cat2 每个类别都有多个 Y 值 如果每个 X 值的 Y 值的数量相同 我可以使用以下代码使其工作 import numpy as np import mat
  • 有人用过 Dabo 做过中型项目吗? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我们正处于一个新的 ERP 风格的客户端 服务器应用程序的开始阶段 该应用程序是作为 Python 富客户端开发的 我们目前正在评估 Dabo
  • 导入错误:没有名为 site 的模块 - mac

    我已经有这个问题几个月了 每次我想获取一个新的 python 包并使用它时 我都会在终端中收到此错误 ImportError No module named site 我不知道为什么会出现这个错误 实际上 我无法使用任何新软件包 因为每次我
  • 如何使用 Pycharm 安装 tkinter? [复制]

    这个问题在这里已经有答案了 I used sudo apt get install python3 6 tk而且效果很好 如果我在终端中打开 python Tkinter 就可以工作 但我无法将其安装在我的 Pycharm 项目上 pip
  • Statsmodels.formula.api OLS不显示截距的统计值

    我正在运行以下源代码 import statsmodels formula api as sm Add one column of ones for the intercept term X np append arr np ones 50

随机推荐

  • 矩阵的投影、线性拟合与最小二乘法

    概要 投影矩阵 如果一个b向量进行矩阵运算 Pb 那么向量b就会投影要A的列空间的最近点 目录 一 矩阵的四大基础子空间 二 投影矩阵 三 最小二乘法 一 矩阵的四大基础子空间 一个矩阵有4个子空间 分别是行空间 零空间 列空间和左零空间
  • C#中的委托、事件与接口

    C 中的委托 事件与接口 一 委托 一 委托链 二 匿名函数 三 Lamda语句 二 事件 三 接口 一 委托 委托 将方法以变量的形式传递 以方法的形式执行 注意 赋值方法的返回类型 参数要与委托的一致 如委托定义的参数类型是string
  • 微信小程序上传文件组件

    微信小程序上传文件 一 说明 该拍照组件带有微信授权相机功能 会结合后端接口 将上传的图片以数组集合的形式传值给父级页面 注意 组件适用于 单独上传图片 不携带参数 结合后端接口返回路径之后 再调用另外的保存接口 携带参数与图片提交的场景
  • 抓取第三方网站数据

    最近需要把某网站的统计数据聚合到我们自己的系统里 但是该网站没有提供标准API 所以就尝试自己抓取了一下 本文总结一下一般的方法 分析服务地址 通常网站有2种做法 一种是后端渲染 直接把渲染后的完整界面呈现在浏览器 另一种前端是静态页面 通
  • mybatis plus中的${ew.sqlSegment},${ew.sqlSelect},${ew.customSqlSegment},${ew.sqlSet}使用

    ew是mapper方法里的 Param Constants WRAPPER Wrapper queryWrapper对象 首先判断ew emptyOfWhere是否存在where条件 有的话再拼接上去 ew customSqlSegment
  • java毕业设计——基于JSP+JavaBean+sqlserver的在线购物系统设计与实现(毕业论文+程序源码)——在线购物系统

    基于JSP JavaBean sqlserver的在线购物系统设计与实现 毕业论文 程序源码 大家好 今天给大家介绍基于JSP JavaBean sqlserver的在线购物系统设计与实现 文章末尾附有本毕业设计的论文和源码下载地址哦 需要
  • 品味树莓派:GPIO Zero库使用入门

    文章目录 目的 基础说明 入门使用 LED PWMLED Button 更多入门例程 类基础说明 注意事项 总结 目的 树莓派有很多GPIO口可供用户使用 官方同时也提供了一些方式来操作这些IO口 其中目前主要推荐的是基于Python的GP
  • 1、什么是Shader

    什么是Shader Shader 中文名为着色器 Shader其实就是专门用来渲染图形的一种技术 通过shader 我们可以自定义显卡渲染画面的算法 使画面达到我们想要的效果 小到每一个像素点 大到整个屏幕 Shader分为两类 顶点Sha
  • 使用Gradle构建SpringBoot工程系列:第八篇:使用spring-data-jpa 实现数据持久化

    本篇文章是SpringBoot 系列文章的第八篇文章 由于本人工作原因 中断了一段时间 接下来的一段时间里 将陆续更新本系列的其他文章 回归Spring Boot技术体系 记录本人学习和使用Gradle构建spring Boot工程的过程
  • C/C++蓝桥杯三升序列

    本题答案可能是错的 我算出的是180414 和很多博主的答案不一样 我也不太懂哪里有问题 大家可以探讨一下 题目描述 对于一个字母矩阵 我们称矩阵中的一个三升序列是指在矩阵中找到三个字母 它们在同一行 同一列 或者在同一45 度的斜线上 这
  • OpenFlow流表_时间因素

    目标 现有拓扑结构如下的网络结构 s1 s4为交换机 h1 h9为主机 现欲让h1和h2白天ping不通 晚上ping的通 拓扑结构 s1
  • es6查找指定字符下标,并把第一个字符前面的内容删掉

    前言 用es6实现查找指定字符下标 并把第一个字符前面的内容删掉 原字符串 abc 123 bcd 444 目标字符 123 bcd 444 实现方法 let abc abc 123 bcd 444 let mmm abc indexOf
  • springcloud与springboot版本列表查看及依赖关系查看

    一 版本规则说明 1 springboot版本 Spring Boot 2 2 5 RELEASE表示主版本 次版本 增量版本 Bug修复 主要 版本中的第一个数字 2 和 3 是 Python 的著名 主要版本 主要部分是基于日历的最常见
  • (华硕)电脑第一次开机蓝屏,二次开机启动

    华硕主板 第一次开机蓝屏 二次开机启动 使用了无缓存的M 2 SSD 2个通道的SSD 修改开机模式 改成兼容模式启动
  • 【H5】阻止H5页面播放视频默认全屏

    老是看到有人找不到阻止视频默认全屏的问题 看到别人发的帖子不是隐藏video标签使用canvas绘制视频就是使用插件来禁止视频默认全屏的问题 其实没有那么麻烦的只需要设置一下属性就可以了 x5 playsinline true 安卓需要设置
  • gRPC-Java实现各种服务类型

    gRPC实现 借助gRPC 我们可以在一个 proto文件中定义一次服务 并以gRPC支持的任何语言生成客户端和服务器 而这又可以在从大型数据中心内的服务器到电脑的各种环境中运行 gRPC为您处理不同的语言和环境 还获得了使用协议缓冲区的所
  • 设计模式-Visitor模式(访问者模式)

    什么是访问者模式 另一个例子 双重分发 开闭原则 对扩展开放 对修改关闭 优缺点 什么是访问者模式 将数据结构与处理分离开来 比如一个人 他有自己的名字 他可以吃东西 这里的 人 就是一个数据结构 名字是属性 吃东西是行为方法 处理 pub
  • Apache Tomcat Websocket 教程

    WebSocket 是一种计算机通信协议 旨在在 Web 浏览器和 Web 服务器中实现 但它可以被任何客户端或服务器应用程序使用 WebSocket 协议是一个独立的基于 TCP 的协议 它与 HTTP 的唯一关系是它的握手被 HTTP
  • 过来人告诉你:Java学到什么程度可以找工作?

    大部分初次学习Java的同学都非常关注自己学到什么程度可以找工作就业 因为学习的目的一方面在于掌握知识 提高技能 另一方面就是就业谋生 今天笔者就来跟大家聊一聊一下Java学习到什么地步可以面试找工作 任何企业 不论大小 对于初级的Java
  • python 之 进程与线程区别、GIL锁产生背景及对Python性能的影响?python的多线程是假的,为啥还用多线程

    一 进程与线程区别 根本区别 进程是操作系统资源分配的基本单位 每个进程都有自己独立的地址空间 数据 堆栈和状态 线程是处理器任务调度和执行的基本单位 一个进程可以有多个线程 这些线程共享进程的地址空间和资源 资源开销 内存分配 进程创建新