当前位置: 首页 > news >正文

什么是GIL锁,有什么作用?python的垃圾回收机制是什么样的?解释为什么计算密集型用多进程,io密集型用多线程。

1 什么是gil锁,有什么作用?
2 python的垃圾回收机制是什么样的?
3 解释为什么计算密集型用多进程,io密集型用多线程。

1 什么是gil锁,有什么作用?

1 GIL:Global Interpreter Lock又称全局解释器锁。本质就是一个互斥锁,
2 保证了cpython进程中得每个线程必须获得这把锁才能执行,不获得不能执行
3 使得在同一进程内任何时刻仅有一个线程在执行
4 gil锁只针对于cpython解释器----》JPythonPyPyCPython***作用:***1 保护Python对象免受多线程并发访问的破坏。2 确保在多线程环境中只有一个线程执行Python字节码。3 GIL的存在使得在CPU密集型任务中,Python的多线程并不能充分发挥多核CPU的优势。因为只有一个线程能够执行字节码,其他线程会被阻塞。***为什么要有gil锁?***python是动态强类型语言,因为有垃圾回收机制,如果同一个进程下有多个线程同时在执行,垃圾回收是垃圾回收线程【同一个进程下变量是共享的】,该线程做垃圾回收时,如果其他线程在运行,就可能会出并发安全的问题【数据安全的问题】,由于当时,只有单核cup【即便开启多线程,同一时刻,也只有一个线程在运行】,作者就强行做了一个GIL锁,保证在一个进程内,同一时刻只有一个线程执行,目的是为了防止垃圾回收线程做垃圾回收时,出现数据紊乱问题,所以加了gil锁**垃圾回收**是垃圾回收线程,它在执行的时候,其他线程是不能执行的,而限于当时的条件,只有单核cpu,所以作者直接做了个GIL锁,保证一个进程内同一时刻只有一个线程在执行。python使用引用计数为主,标记清楚和隔代回收为辅来进行内存管理。所有python脚本中创建的对象,都会配备一个引用计数,来记录有多少个指针来指向它。当对象的引用技术为0时,会自动释放其所占用的内存。假设有2个python线程同时引用一个数据(a=100,引用计数为1),2个线程都会去操作该数据,由于多线程对同一个资源的竞争,实际上引用计数为3,但是由于没有GIL锁,导致引用计数只增加1(引用计数为2)这造成的后果是,当第1个线程结束时,会把引用计数减少为1;当第2个线程结束时,会把引用计数减少为0;当下一个线程再次视图访问这个数据时,就无法找到有效的内存了
import threading# 共享变量
counter = 0def count_up():global counterfor _ in range(1000000):counter += 1def count_down():global counterfor _ in range(1000000):counter -= 1# 创建两个线程分别执行计数操作
t1 = threading.Thread(target=count_up)
t2 = threading.Thread(target=count_down)# 启动线程
t1 .start()
t2.start()# 等待两个线程执行完成
t1 .join()
t2.join()print("Counter:", counter)在上述代码中,我们有两个线程,一个递增 counter,一个递减 counter。
理论上,counter 的最终值应该是 0。但是由于GIL的存在,多线程并发执行时,由于GIL的保护,
实际上可能并不会得到正确的结果。在这个例子中,counter 的最终值可能不是 0,
因为两个线程在修改 counter 时可能会发生竞争条件。

2 python的垃圾回收机制是什么样的?

1 参考文章:https://www.jianshu.com/p/52ab268901142 什么是垃圾回收?编程语言在运行过程中会定义变量--->申请了内存空间---》后期变量不用了---》这个内存空间应该释放掉,有些编程语言,这个操作,需要程序员自己做(c),像java,python,go这些语言,都自带垃圾回收机制,可以自动回收内存空间,gc机制。3 不同语言垃圾回收的方式是不一样的,python是使用如下三种方式做gc,以引用计数为主,标记-清除和分代回收两个算法为辅(1)引用计数算法(reference counting):每个对象都有一个引用次数的计数属性,如果对象被引用了,那这个数就会 加1,如果引用被删除,引用计数就会 减1,那么当该对象的引用计数为0时,就说明这个对象没有被使用,垃圾回收线程就会把它回收掉,释放内存。-有问题:循环引用问题---》回收不了(2) 标记-清除算法(Mark and Sweep)-解决引用计数无法回收循环引用的问题对象之间通过引用连在一起,节点就是各个对象,从一个根对象向下找对象,可以到达的标记为活动对象,不能到达的是非活动对象,而非活动对象就是需要被清除的。(3) 分代回收算法(Generational garbage collector)-分代回收是解决垃圾回收效率问题算法原理是Python把对象的生命周期分为三代,分别是第0代、第1代、第2代。每一代使用双向链表来标记这些对象。每一代链表都有总数阈值,当达到阈值的时候就会出发GC回收,将需要清除的清除掉,不需要清除的移到下一代。以此类推,第2代中的对象存活周期最长的对象。注意:python垃圾回收最核心是:引用计数----》标记清除解决引用计数的循环引用问题---》分代回收解决垃圾回收的效率问题。

import gc# 创建一个循环引用的对象
class CircularReference:def __init__(self):self.circular_ref = None# 创建循环引用
obj1 = CircularReference()
obj2 = CircularReference()
obj1.circular_ref = obj2
obj2.circular_ref = obj1# 手动断开引用,使引用计数变为零
obj1 = None
obj2 = None# 手动触发垃圾回收
gc.collect()# 由于循环引用,垃圾回收器会将它们回收
print(gc.garbage)在上述代码中,`CircularReference` 类创建了两个对象 `obj1` 和 `obj2`,
它们相互引用形成了循环引用。当手动断开对 `obj1` 和 `obj2` 的引用后,手动调用 `gc.collect()` 
来触发垃圾回收。垃圾回收器会检测到这个循环引用并将其回收。回收后,`gc.garbage` 列表中将包含被
回收的对象,我们可以通过查看这个列表来确认回收是否成功。

3 解释为什么计算密集型用多进程,io密集型用多线程。

计算是消耗cpu的:代码执行,算术,for都是计算
io不消耗cpu:打开文件,写入文件,网络操作都是io-如果遇到io,该线程会释放cpu的执行权限,cpu转而去执行别的线程由于python有GIL锁,开启多条线程,同一时刻,只能有一条线程在执行。
如果是***计算密集型***开了多线程,同一时刻,只有一个线程在执行,多核cpu,就会浪费多核优势;
如果是计算密集型,我们希望多个核(cpu),都干活,同一个进程下绕不过gil锁。所以我们开启多进程,
gil锁只能锁住某个进程中的线程,开启多个进程,就能利用多核优势。***io密集型***只要遇到io,就会释放cpu执行权限,进程内开了多个io线程,线程多半都在等待,
开启多进程是不能提高效率的,反而开启进程很耗费资源,所以使用多线程即可。计算密集型任务主要是由CPU计算驱动,对CPU的利用率要求较高。
I/O密集型任务主要是由I/O操作驱动,对CPU的利用率较低。

计算密集型任务使用多进程

import multiprocessingdef calculate_square(numbers):result = []for number in numbers:result.append(number * number)print("Result (in process):", result)if __name__ == "__main__":numbers = list(range(1, 6))# 使用多进程process = multiprocessing.Process(target=calculate_square, args=(numbers,))process.start()process.join()print("Main process continues...")

I/O密集型任务使用多线程

import threading
import timedef simulate_io_operation():print("Start I/O operation...")time.sleep(2)  # 模拟I/O操作,比如文件读写或网络请求print("I/O operation completed.")if __name__ == "__main__":# 使用多线程t1= threading.Thread(target=simulate_io_operation)t2= threading.Thread(target=simulate_io_operation)t1.start()t2.start()t1.join()t2.join()print("Main thread continues...")

在这两个例子中,计算密集型任务使用了多进程,而I/O密集型任务使用了多线程。这是因为计算密集型任务中的 GIL 限制了多线程的效果,而I/O密集型任务中可以充分利用多线程的并发性。

相关文章:

什么是GIL锁,有什么作用?python的垃圾回收机制是什么样的?解释为什么计算密集型用多进程,io密集型用多线程。

1 什么是gil锁,有什么作用? 2 python的垃圾回收机制是什么样的? 3 解释为什么计算密集型用多进程,io密集型用多线程。 1 什么是gil锁,有什么作用? 1 GIL:Global Interpreter Lock又称全局解释器…...

Postman如何发送Https请求

Postman如果想要发送Https请求,需要从设置中将SSL安全认证禁用...

Redis集群启动

配置项 # 允许Redis监听所有网络接口的IP地址,即0.0.0.0。这意味着Redis可以接受来自任何网络接口的连接。 bind 0.0.0.0 # 关闭保护模式。在保护模式下,Redis只接受来自本机的连接。关闭保护模式后,Redis可以接受来自任何网络接口的连接。 protected-mode no # 在后…...

使用proxy把后端返回的图片域名替换成目标域名

proxy 对象用于创建一个对象的代理,是在目标对象之前架设一个拦截,外界对该对象的访问,都必须先通过这个拦截。通过这种机制,就可以对外界的访问进行过滤和改写。 ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例。…...

css实现div倾斜效果

效果如下&#xff1a; <!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title></head> <style> *{margin:0;padding: 0;} .box1{margin:30px 100px;width:100px;height:200px;background:blueviolet;} …...

算法学习打卡day45|动态规划:股票问题总结

Leetcode股票问题总结篇 动态规划的股票问题一共六道题&#xff0c;买卖股票最佳时机和买卖股票手续费都是一个类型的问题&#xff0c;维护好买入和卖出两个状态即可&#xff0c;方法一摸一样。而冷冻期也差不多就是状态多了点&#xff0c;买入、保持卖出、当日卖出、以及冷冻期…...

内网环境下让容器上网,并制作一个httpd容器

1.下载基础镜像 上一次&#xff0c;我们通过正向互联网代理在内网环境中&#xff0c;搭建了一个docker环境&#xff0c;具体环境如下&#xff1a; 1) 内网docker服务器&#xff1a;192.168.123.1&#xff0c;操作系统为&#xff1a;redhat 7.9 2) 代理服务器(可通外网)&#…...

多个Obj模型合并

MergeObj&#xff08;合并Obj模型&#xff09; 1 概述 由于项目原因&#xff0c;需要下载谷歌地图上的模型&#xff0c;关于谷歌模型下载的&#xff0c;见我的CSDN博客. 由于下载谷歌地图上的数据&#xff0c;会分多个模块下载。下载完成后&#xff0c;怎么合并&#xff0c;在…...

Qt调用python写好的函数,利用Python丰富的图像处理库来完成各种任务

一、前言 近年来,Python已经成为一种广泛应用于科学计算、数据分析和机器学习等领域的强大编程语言。其丰富的生态系统和大量的开源库使得Python成为处理图像、音频、视频和其他多媒体数据的理想选择。在图像处理领域,Python提供了许多方便的函数和库,如OpenCV、PIL(Pytho…...

第六章:接口

系列文章目录 文章目录 系列文章目录前言一、接口二、实现接口与继承类三、接口的多态特性总结 前言 接口是更加抽象的类。 一、接口 usb插槽就是现实中的接口&#xff0c;厂家都遵守了统一的规定包括尺寸&#xff0c;排线等。这样的设计在java编程中也是大量存在的。 packa…...

【Java 进阶篇】JQuery DOM操作:CRUD操作的前端魔法

在前端开发的舞台上&#xff0c;CRUD&#xff08;Create, Read, Update, Delete&#xff09;操作是一种极为重要的技能&#xff0c;它涉及对页面元素的增删改查。而JQuery&#xff0c;这位前端开发的魔法师&#xff0c;为我们提供了便捷而强大的方法&#xff0c;使得CRUD操作变…...

如何实现Redisson分布式锁

首先&#xff0c;不要将分布式锁想的太复杂&#xff0c;如果我们只是平时业务中去使用&#xff0c;其实不算难&#xff0c;但是很多人写的文章不能让人快速上手&#xff0c;接下来&#xff0c;一起看下Redisson分布式锁的快速实现 Redisson 是一个在 Redis 的基础上实现的 Java…...

Kafka(三)生产者发送消息

文章目录 生产者发送思路自定义序列化类配置生产者参数提升吞吐量 发送消息关闭生产者结语示例源码仓库 生产者发送思路 如何确保消息格式正确的前提下最终一定能发送到Kafka? 这里的实现思路是 ack使用默认的all开启重试在一定时间内重试不成功&#xff0c;则入库&#xff…...

2020年五一杯数学建模C题饲料混合加工问题解题全过程文档及程序

2020年五一杯数学建模 C题 饲料混合加工问题 原题再现 饲料加工厂需要加工一批动物能量饲料。饲料加工需要原料&#xff0c;如加工猪饲料需要玉米、荞麦、稻谷等。加工厂从不同的产区收购了原料&#xff0c;原料在收购的过程中由于运输、保鲜以及产品本身属性等原因&#xff…...

公益SRC实战|SQL注入漏洞攻略

目录 一、信息收集 二、实战演示 三、使用sqlmap进行验证 四、总结 一、信息收集 1.查找带有ID传参的网站&#xff08;可以查找sql注入漏洞&#xff09; inurl:asp idxx 2.查找网站后台&#xff08;多数有登陆框&#xff0c;可以查找弱口令&#xff0c;暴力破解等漏洞&…...

Word软件手动安装Zotero插件

文章目录 Word软件手动安装Zotero插件方法一方法二 参考资料 Word软件手动安装Zotero插件 方法一 关闭word在zotero中依次点击编辑—首选项—引用—文字编辑软件—重新安装加载项Microsoft word 方法二 寻找Zotero.dotm存储位置&#xff0c; 例如D:\Program Files\Zotero\ext…...

idea 插件推荐第二期

文章目录 便捷开发CodeGlance Pro (代码缩略图)GenerateAllSetter&#xff08;快速生成对象所有set方法&#xff09;GsonFormatPlus&#xff1a;json转实体RestfulToolkitX&#xff08;找到controller快捷请求接口&#xff09; 美化activate-power-mode-x (敲击计数、动效)Nyan…...

plsql查询中文出现乱码

添加环境变量&#xff1a;如下 变量名&#xff1a;NLS_LANG 变量值&#xff1a;SIMPLIFIED CHINESE_CHINA.ZHS16GBK 变量名&#xff1a;TNS_ADMIN 变量值&#xff1a;D:\instantclient_11_2\network\admin 在Path中添加instantclient_11_2存放路径...

【Docker】五分钟完成Docker部署Java应用,你也可以的!!!

文章目录 前言一、部署步骤1.项目结构2.Dockerfile3.docker-compose.yml4.启动5.常用命令 总结 前言 本文基于Docker Compose部署Java应用&#xff0c;请确保你已经安装了Docker和Docker Compose。 十分钟就能上手docker&#xff1f;要不你也试试&#xff1f; 一、部署步骤 1…...

如何准备2024年的系统设计面试?

1 前言 如果你正在准备软件工程师或软件开发人员的面试,那么你可能知道由于其开放性质和广泛性,准备系统设计是多么困难,但同时你也不能忽略它。在软件工程界,如果你正在申请高级工程师/主管/架构师或更高级别的角色,系统设计是最受追捧的技能,也是整个过程中最重要的环节之一…...

OpenClaw版本升级:Qwen3-4B模型与新框架特性的兼容性

OpenClaw版本升级&#xff1a;Qwen3-4B模型与新框架特性的兼容性 1. 为什么需要关注版本升级 上周五晚上11点&#xff0c;我的OpenClaw突然弹出一条警告&#xff1a;"当前版本(v0.8.3)将在48小时后停止维护"。这个深夜警报让我意识到&#xff0c;是时候处理这个技术…...

支持RTX 30/40系显卡:PyTorch-2.x-Universal-Dev-v1.0镜像GPU验证指南

支持RTX 30/40系显卡&#xff1a;PyTorch-2.x-Universal-Dev-v1.0镜像GPU验证指南 1. 引言&#xff1a;为什么需要验证GPU环境 在深度学习项目开发中&#xff0c;GPU加速是提升模型训练效率的关键因素。特别是对于RTX 30/40系列显卡用户&#xff0c;正确配置CUDA环境与PyTorc…...

OpenClaw故障排查大全:千问3.5-27B接口调用常见错误解决

OpenClaw故障排查大全&#xff1a;千问3.5-27B接口调用常见错误解决 1. 开篇&#xff1a;当OpenClaw遇上千问3.5-27B 上周深夜&#xff0c;我的OpenClaw突然罢工了——一个原本运行良好的自动化脚本在调用千问3.5-27B模型时频繁报错。作为个人效率工具的重度用户&#xff0c;…...

硬件工程师的福音:用Beyond Compare 4表格比对功能,5分钟搞定BOM清单版本差异检查

硬件工程师的效率革命&#xff1a;Beyond Compare 4表格比对功能深度解析 在硬件研发的日常工作中&#xff0c;BOM清单的版本管理往往是最令人头疼的环节之一。每次PCB设计的小版本迭代——无论是物料替换、数量调整还是参数优化——都需要工程师花费大量时间核对变更细节。传统…...

实战应用开发:基于快马平台构建集成heic转换功能的图片管理系统

最近在做一个图片管理系统的项目&#xff0c;其中遇到一个很实际的需求&#xff1a;用户上传的HEIC格式照片需要自动转换成通用的JPG格式。这个功能看似简单&#xff0c;但实际开发中需要考虑很多细节。下面分享下我在InsCode(快马)平台上实现这个功能的完整过程。 项目整体架构…...

飞机喷涂废气治理厂家丨一场看不见的“废气治理战”如何打响?

你有没有注意过&#xff0c;当你透过舷窗望向停机坪时&#xff0c;那些静静停靠的飞机&#xff0c;机身光洁如镜&#xff0c;涂装色彩鲜明&#xff1f;一架飞机交付使用&#xff0c;到每隔数年的定期大修&#xff0c;飞机都需要经历复杂的喷涂过程。这层看似简单的“外衣”&…...

STM32串口发送字符串的底层机制与优化实践

1. STM32串口发送字符串的底层机制解析在嵌入式开发中&#xff0c;USART&#xff08;通用同步异步收发传输器&#xff09;是最常用的外设之一。当我们需要通过串口发送字符串时&#xff0c;实际上是将数据写入发送数据寄存器&#xff08;TDR&#xff09;&#xff0c;然后由硬件…...

GetQzonehistory:终极QQ空间回忆一键保存指南

GetQzonehistory&#xff1a;终极QQ空间回忆一键保存指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 还在担心QQ空间里那些珍贵的青春记忆会随着时间消失吗&#xff1f;GetQzonehis…...

点集相等概念表明流传2300多年使世人深信不疑的直线公理将无穷多各异直线误为同一线

黄小宁 “科学”共识&#xff1a;在初等数学领域绝对不可能有颠覆性创新&#xff0c;谁若说“已非常成熟”的初等数学存在重大错误那就说明谁有“自大狂型精神病”。 “实数集”R可几何化为R轴。与x∈R相异&#xff08;等&#xff09;的实数均可表为yxδ&#xff08;增量δ可…...

电力系统稳定器与静态无功补偿器联合提升暂态稳定性Simulink仿真模型研究

使用电力系统稳定器&#xff08;PSS&#xff09;和静态无功补偿器&#xff08;SVC&#xff09;提高暂态稳定性的simulink仿真模型电力系统这玩意儿最怕的就是突然来个大扰动&#xff0c;比如短路故障或者大负荷切换。这时候发电机的功角曲线要是收不住&#xff0c;分分钟全网停…...