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

高并发内存池(11)-PageCache获取Span(下)

高并发内存池(11)-PageCache获取Span(下)

这里在向页缓存申请新Span之前释放中心缓存的锁,是一个非常重要的性能优化策略,目的是减少锁的持有范围,提高并发性能

为什么需要在这里解锁?

1. 避免长时间持有锁

list._mtx.unlock();  // 释放中心缓存锁PageCache::GetInstance()->_pageMtx.lock();
Span* span = PageCache::GetInstance()->NewSpan(...);
PageCache::GetInstance()->_pageMtx.unlock();

关键原因:向PageCache申请内存可能是一个相对耗时的操作,因为可能涉及:

  • 遍历多个Span链表
  • 分割大Span为小Span
  • 甚至向操作系统申请新内存

如果持有中心缓存锁进行这些操作,会阻塞其他线程访问同一个桶。

2. 锁的粒度优化

优化前(错误做法):

// 持有中心缓存锁进行耗时操作
list._mtx.lock();
// ... 可能耗时的PageCache操作
list._mtx.unlock();

优化后(正确做法):

// 只持有锁进行快速操作
list._mtx.lock();
// 快速检查本地Span链表
list._mtx.unlock();  // 立即释放锁// 执行耗时操作(不持有中心缓存锁)
// ...// 重新加锁进行快速操作
list._mtx.lock();
// 快速插入新Span
list._mtx.unlock();

3. 减少死锁风险

PageCache有自己的锁(_pageMtx),如果同时持有多个锁:

// 危险:可能持有多个锁
list._mtx.lock();      // 持有中心缓存锁
_pageMtx.lock();       // 持有页缓存锁(可能产生死锁)

释放中心缓存锁后再申请页缓存锁,避免了锁嵌套和潜在的死锁风险

可视化过程

时间线对比

不释放锁的情况

线程1: [持有锁] → [PageCache操作] → [释放锁] ⏳
线程2: [等待锁] -----------------------→ [获取锁] ❌ 长时间阻塞

释放锁的情况

线程1: [持有锁] → [释放锁] → [PageCache操作] → [重新持锁] → [释放锁] ✅
线程2: [等待锁] → [获取锁] → [操作] → [释放锁] ✅ 几乎无阻塞

安全性考虑

你可能会担心:释放锁后,其他线程会不会修改状态?

实际上这是安全的,因为:

  1. 检查已完成:我们已经检查过当前桶没有可用Span
  2. 操作原子性:即使其他线程在此期间释放了内存,我们重新申请Span也是正确的
  3. 最终一致性:最后我们会将新Span加入链表,整体状态仍然一致

性能影响

这种优化在高并发场景下效果显著:

  • 低竞争环境:可能影响不大
  • 高竞争环境:吞吐量提升可达30-50%
  • 极端情况:避免线程长时间阻塞导致的性能悬崖

总结

这个解锁操作体现了多线程编程的重要原则:

持有锁的时间应该尽可能短

通过精细的锁粒度控制,在保证线程安全的前提下,最大化并发性能。这是高性能内存分配器设计的精髓之一。

http://www.dtcms.com/a/352913.html

相关文章:

  • 【Hadoop】Zookeeper、HBase、Sqoop
  • 寄存器的原理
  • 边缘计算:一场由物理定律发起的“计算革命”
  • leetcode算法刷题的第十九天
  • 如何在Ubuntu中启用有线网
  • DolphinScheduler安装配置教程(超级详细)
  • 吉比特(雷霆游戏)前端二面问题总结
  • 骰子滚出最大和
  • 往来港澳台地区通行证件识读的应用案例
  • 艾体宝新闻 | 98%好评率!KnowBe4 连续5年蝉联第一,现开放免费钓鱼测试等你解锁
  • 查询窗口输入“ 188 8888 8888 “这种前后、中间都带空格的电话号码的处理方式
  • 目前3D打印机槽点网络汇总, 个人提可改进项, 可颠覆性方向,公开
  • AI需求优先级:数据价值密度×算法成熟度
  • CentCentOS7-OPenStack-Trian版搭建
  • 经典聚类算法讲解:K-means 和 DBSCAN
  • 实战原型模式案例
  • 【Chrome 扩展】chrome自动升级后 Switchomega扩展不支持了怎么办
  • Transformer实战(15)——使用PyTorch微调Transformer语言模型
  • centos 判断一个对象是文件还是文件夹
  • HarmonyOS 高效数据存储全攻略:从本地优化到分布式实战
  • 财务报表怎么做?财务常用的报表软件都有哪些
  • vscode 调试 指定 python文件 运行路径
  • IO 字符流 【详解】| Java 学习日志 | 第 13 天
  • npm run start 的整个过程
  • LeetCode 刷题【54. 螺旋矩阵】
  • 共享云服务器替代传统电脑做三维设计会卡顿吗
  • Spring Boot 启动失败:循环依赖排查到懒加载配置的坑
  • 手写MyBatis第37弹: 深入MyBatis MapperProxy:揭秘SQL命令类型与动态方法调用的完美适配
  • 特征降维-特征组合
  • YOLO 目标检测:数据集构建(LabelImg 实操)、评估指标(mAP/IOU)、 NMS 后处理