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

手写muduo网络库(零):多线程中使用 weakptr 跨线程监听生命状态

在着手手写 muduo 网络库时,多线程编程中的对象生命周期管理是绕不开的关键技术点。std::weak_ptr作为 C++ 标准库的重要工具,能帮助我们在多线程环境下优雅、安全地监听对象生命状态,为网络库的稳定性和可靠性奠定基础。接下来,我们深入探讨这一前置知识,并结合实际场景,为手写 muduo 网络库做好技术储备。

一、核心概念解析​

1.1 std::shared_ptr与std::weak_ptr的协作机制​

在 muduo 网络库中,会存在大量需要多线程共享访问的对象,如连接管理对象、事件循环对象等。std::shared_ptr通过引用计数管理对象生命周期,在共享这些对象时,引用计数随着新std::shared_ptr的创建而增加,随着std::shared_ptr的销毁而减少,引用计数为 0 时对象自动销毁,为对象共享提供了基础保障。​

std::weak_ptr则是对std::shared_ptr所管理对象的弱引用,不影响对象生命周期,却能检查对象是否存在。在手写 muduo 时,std::weak_ptr可用于在多个线程交互场景下,安全判断对象是否存活。比如,当一个线程负责处理网络连接,另一个线程可能对连接对象进行销毁操作,std::weak_ptr就能避免处理线程访问已销毁的连接对象。​

1.2 线程安全特性​

std::shared_ptr和std::weak_ptr的引用计数操作具备线程安全性,这对于多线程的 muduo 网络库来说,保证了对象生命周期管理在多线程环境下的正确性。但要注意,对象本身的读写操作并非线程安全,在手写 muduo 时,我们需要借助互斥锁等同步机制,来确保对象访问的线程安全,防止出现数据竞争问题。

二、实现步骤与代码示例

#include <iostream>
#include <memory>
#include <thread>
#include <chrono>
#include <mutex>class Monitorable {
public:Monitorable() { std::cout << "Monitorable created" << std::endl; }~Monitorable() { std::cout << "Monitorable destroyed" << std::endl; }void doWork() {std::lock_guard<std::mutex> lock(mtx_);std::cout << "Working..." << std::endl;}private:std::mutex mtx_;
};void workerThread(std::weak_ptr<Monitorable> weakObj) {// 模拟耗时操作std::this_thread::sleep_for(std::chrono::seconds(1));// 尝试锁定弱引用,检查对象是否存活if (auto sharedObj = weakObj.lock()) {// 对象存活,可以安全使用sharedObj->doWork();} else {// 对象已销毁std::cout << "Object expired, skipping work" << std::endl;}
}int main() {{auto sharedObj = std::make_shared<Monitorable>();std::thread t(workerThread, sharedObj);t.detach(); // 分离线程,让它在后台运行// 主线程作用域结束前,sharedObj可能被销毁} // sharedObj在此处被销毁// 主线程继续执行其他任务std::this_thread::sleep_for(std::chrono::seconds(2));return 0;
}
  • 线程函数参数传递:在workerThread 函数中,使用std::weak_ptr 作为参数接收对象引用。这样做的好处是,std::weak_ptr 不会增加对象的引用计数,从而不会影响对象的正常生命周期管理。即使主线程中std::shared_ptr 被销毁,workerThread 中的std::weak_ptr 仍能用于检查对象状态。​
  • 对象状态检查方式:在workerThread 函数中,通过调用weakObj.lock() 尝试获取对象的 std::shared_ptr 。如果对象仍然存在,lock() 会返回一个有效的 std::shared_ptr ,此时可以安全地访问对象的成员函数;如果对象已被销毁,lock() 则返回 nullptr ,从而避免了悬空指针的风险。​
  • 线程安全保障措施:在Monitorable 类的doWork 函数中,使用std::lock_guard<std::mutex> 来保证多线程访问对象资源时的线程安全。通过互斥锁,确保在同一时刻只有一个线程能够执行doWork 函数,防止数据竞争和不一致的情况发生。

 三、注意要点

  • 对象销毁延迟:虽然std::weak_ptr 的状态检查是原子操作,但对象的实际销毁可能会有延迟,这取决于 std::shared_ptr 的释放顺序。因此,在检查对象状态和实际使用对象之间,仍需考虑对象可能被销毁的情况,避免出现逻辑错误。​
  • 线程安全补充:尽管std::shared_ptr 和 std::weak_ptr 的引用计数操作线程安全,但在使用 lock() 返回的 std::shared_ptr 访问对象时,仍要结合其他同步机制(如互斥锁),确保对象的读写操作在多线程环境下的安全性。​

掌握std::weak_ptr在多线程中监听对象生命状态的方法,是手写 muduo 网络库的重要前置知识。它能帮助我们有效管理对象生命周期,避免悬空指针等问题,为后续构建稳定、可靠的 muduo 网络库打下坚实基础。

http://www.xdnf.cn/news/911125.html

相关文章:

  • 【android bluetooth 协议分析 02】【bluetooth hal 层详解 8】【高通蓝牙hal-进程被杀之前日志收集流程】
  • jmeter之导出接口
  • 立定跳远-二分
  • 20250606-C#知识:委托和事件
  • 企业引入数字孪生,优化决策,提升市场竞争力的秘诀
  • 缓存一致性的形式化定义
  • UVM环境打印如何显示时间单位
  • 仿射变换、根据特征点进行仿射变换
  • HarmonyOS运动开发:如何用mpchart绘制运动配速图表
  • 计算与分析2-深度学习
  • F5 – TCP 连接管理:会话、池级和节点级操作
  • 嵌入式Linux下如何启动和使用Docker
  • 【数据结构】图
  • FPGA 动态重构配置流程
  • CVAT标注服务
  • 中国移动6周年!
  • C++.OpenGL (10/64)基础光照(Basic Lighting)
  • 2025年6月6日15:48:23
  • [蓝桥杯]防御力
  • Source insight 4自用技巧整理
  • webstorm 配置 Prettier
  • 每次clone都会有:Enter passphrase for key ‘/Users/xxx/.ssh/id_rsa‘:
  • JavaScript操作数组、字符串、对象的一些方法
  • vcs仿真产生fsdb波形的两种方式
  • YOLO训练保持原有识别能力
  • maven私服
  • JAVA元编程
  • QPS、TPS、RT、IOQS、并发数等性能名词介绍
  • AI系统提示词:V0
  • C++.OpenGL (9/64)摄像机(Camera)