54、【Ubuntu】【Gitlab】拉出内网 Web 服务:http.server 单/多线程分析(六)

【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除

背景

上篇 blog
【Ubuntu】【Gitlab】拉出内网 Web 服务:http.server 单/多线程分析(五)

分析了 Python GIL 锁在多线程环境下,对 IO 操作(比如 Web 服务并发),仍然有效果的原因,下面继续

Python http.server 单/多线程分析

OK,前面分析了 Python 的 GIL 锁限制了对于一个 Python 进程,即使在多线程环境下,也不能并行的能力,这里需要注意下,并行和并发的区别

  • 并发 :表示多个任务交替推进,宏观上看这些多个任务就是在同时进行(即使 CPU 交替执行,其时间依然很短,给人感觉就是在同时进行一样),不需要 CPU 多核,靠线程切换就能完成 ,所以即使 Python 进程被 GIL 限制,其多线程能力依然对提升 Web 性能依然有效的原因
  • 并行 :表示多个任务真正同时进行(物理上同时运行),需要多核,不能靠多线程切换完成,适合 CPU 密集型任务的处理 ,此时 Python 的 GIL 锁就起作用了,GIL 锁限制了在同一时刻,只能有一个线程在真正执行,也就是说,一个 Python 程序只能用一个 CPU 核来执行任务

    线程 1 和线程 2,此时可以真正物理上同时使用 CPU 核心来执行任务,而不需要等待

可以看到,并发和并行不是一回事,就好比一个人边煮饭边听音乐(通过切换注意力实现任务的并发),而并行是两个人,一个人煮饭,一个人听音乐,这个就是真正的同时进行,所以要注意,高并发 ≠ 高并行

OK,下面再分析下 GIL 锁限制 Python 字节码并行执行的原因

首先,CPython 使用引用计数(Reference Counting) 管理内存 ,在 CPython 中,每个 Python 对象(比如 int,list,str)都有一个 ob_refcnt 字段,记录有多少变量,或容器引用它(注意,引用计数属于 CPython 内部实现机制,需查看解释器源码才能看到 )

举个例子:

  • 当给 a = [1, 2, 3] 赋值时,列表对象的 ob_refcnt 为 1
  • 然后令 b = a,此时 ob_refcnt 会变成 2
  • 当 a 或 b 被删除或重新赋值时,ob_refcnt 会减 1
  • 当 ob_refcnt == 0 时,CPython 会立即释放内存,而不是等垃圾回收

这种机制简单高效,但有一个致命问题,ob_refcnt 的加减不是原子操作!

如果没有 GIL 锁,假设两个线程同时操作同一对象,该对象初始值是 2,俩线程都要对其进行减 1 操作

可以看到,ob_refcnt 被两个线程减引用操作,实际应该变成 0,因为两次减 1,但结果却是 1,此时该对象永远不会被释放,就会造成内存泄漏,更严重的是,如果引用计数错误地编程负数或乱掉,还可能直接导致解释器崩溃(segfault),所以 CPython 必须保证任何修改 Python 对象引用计数的操作,必须是线程安全的

为了解决这个问题,CPython 在其发展的初期(上世纪 90 年代)选择了加一把全局大锁(GIL),所有涉及 Python 对象的操作(包括引用计数增减)都必须持有 GIL,同一时刻只有一个线程能持有 GIL,也就不可能出现并行修改,并且其实现简单,对单线程性能基本无影响

从本质上,GIL 是个懒人方案(也是最简单的方案),用一把锁保护整个解释器,避免给每个对象加锁(那样开销太大)


OK,本篇先到这里,如有疑问,欢迎评论区留言讨论,祝各位功力大涨,技术更上一层楼!!!更多内容见下篇 blog
【Ubuntu】【Gitlab】拉出内网 Web 服务:http.server 单/多线程分析(七)

相关推荐
沫璃染墨4 小时前
从零入门计算机网络系列(十四):TCP报文与字节流本质——从数据封装到报文边界
linux·服务器·网络·网络协议·tcp/ip·tcp
7177776 小时前
Git自建用什么工具比较好:Gitea、Forgejo、GitLab CE与Gitee的选型对比
git·gitlab·gitea
byte轻骑兵6 小时前
【LMP】规范精讲[13]: 参数的户口本、公钥的集装箱与出厂的兜底值
人工智能·网络协议·人机交互·lmp·蓝牙链路管理
流浪0016 小时前
计算机网络篇17:传输层——TCP 超时重传、三次握手与四次挥手,TIME_WAIT 为什么要等 2MSL
网络协议·tcp/ip·计算机网络·三次握手·四次挥手·超时重传
AI 编程助手GPT1 天前
curl 返回成功就能收文件?用本地 HTTP 验证错误页与超时
网络·网络协议·http
流浪0011 天前
计算机网络篇16:传输层——TCP 报头属性字段:16 位窗口大小撑起流量控制,六个标志位标识报文类型
网络协议·tcp/ip·计算机网络·urg紧急指针·tcp报头
apollo_qwe1 天前
接口超时了,前端为什么不能直接重试?
javascript·http
Jongkhurun1 天前
以太网的最小帧长为什么是 64 字节:从 CSMA/CD 冲突窗口推导 64 Byte
网络协议
honsor2 天前
SNMP 读取以太网温湿度传感器数据,监控平台对接实操
物联网·网络协议·tcp/ip
Yves..2 天前
HTTP 协议学习笔记:从报文结构到抓包实践
网络协议·http·fiddler