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

用 RefCounted + WeakPtr 构建线程安全的异步模块

在 Chromium 的多线程异步编程中,合理管理对象生命周期非常关键。本文深入介绍 base::RefCountedThreadSafebase::WeakPtr 的组合使用方法,并通过示例分析其使用要点及易踩的坑。


🌱 基础概念回顾

1. RefCountedThreadSafe<T>

  • 是 Chromium 中线程安全的引用计数基类,用于实现对象的自动释放。

  • 常和 scoped_refptr<T> 配合使用,确保对象在所有引用释放后自动析构。

  • 使用方式:

    class MyObject : public base::RefCountedThreadSafe<MyObject> { public: void DoSomething(); private: friend class base::RefCountedThreadSafe<MyObject>; ~MyObject(); // 析构必须是 private 或 protected };

2. WrapRefCounted

  • 用于在已有裸指针(如 this)的场景下安全构造 scoped_refptr

    scoped_refptr<MyObject> ptr = base::WrapRefCounted(this);


🧪 示例代码:结合 RefCountedThreadSafe 与异步调用

class MyTaskRunner : public base::RefCountedThreadSafe<MyTaskRunner> { public: void PostWork() { base::ThreadPool::PostTask( FROM_HERE, base::BindOnce(&MyTaskRunner::DoWork, base::WrapRefCounted(this))); } private: friend class base::RefCountedThreadSafe<MyTaskRunner>; ~MyTaskRunner() = default; void DoWork() { LOG(INFO) << "Work done!"; } };

✅ 这里通过 WrapRefCounted(this) 绑定异步任务,确保任务执行时对象仍然存活。


⚠️ 易错用法及反例

❌ 错误示例 1:异步任务绑定裸指针,导致 use-after-free

// 错误:this 可能在异步任务执行前就被释放 base::ThreadPool::PostTask( FROM_HERE, base::BindOnce(&MyTaskRunner::DoWork, this));

❌ 错误示例 2:RefCounted 派生类析构函数为 public

class Wrong : public base::RefCountedThreadSafe<Wrong> { public: ~Wrong() {} // ⚠️ 应为 private,否则会导致外部手动 delete,破坏计数机制 };

❌ 错误示例 3:跨线程误用 WeakPtr

base::WeakPtr<MyObject> weak_ptr = weak_factory_.GetWeakPtr(); // 另一线程中使用 weak_ptr -> 不安全!


🔄 RefCounted 与 WeakPtr 的配合使用

当你希望:

  • 对象生命周期由引用计数管理(如模块长时间存在)

  • 同时避免回调访问已经销毁的对象

你可以使用 RefCounted + WeakPtr 同时配合:

class MyService : public base::RefCountedThreadSafe<MyService> { public: MyService() : weak_factory_(this) {} void StartAsyncTask() { base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::BindOnce([](base::WeakPtr<MyService> weak_self) { if (!weak_self || weak_self.WasInvalidated()) return; weak_self->DoSomething(); }, weak_factory_.GetWeakPtr()), base::Seconds(3)); } private: friend class base::RefCountedThreadSafe<MyService>; ~MyService() = default; void DoSomething() { LOG(INFO) << "Safe async work"; } base::WeakPtrFactory<MyService> weak_factory_; };


✅ 推荐使用模式

场景推荐方案
异步回调确保对象存活WrapRefCounted(this)
回调中避免悬挂指针WeakPtr + WasInvalidated() 检查
复杂模块管理生命周期RefCountedThreadSafe + WeakPtrFactory


🧷 调试技巧与源码入口

常见断点位置

# RefCounted 增减引用 break base::internal::RefCountedThreadSafeBase::AddRef break base::internal::RefCountedThreadSafeBase::Release

Chromium 源码路径

  • base/memory/ref_counted.h

  • base/memory/weak_ptr.h

  • 异步任务绑定:base/bind.h, base/task/post_task.h


📌 小结

  • RefCountedThreadSafe 用于自动管理对象生命周期,避免显式 delete。

  • WeakPtr 可防止异步访问已销毁对象,但不能延长生命周期。

  • WrapRefCounted(this) 是在 this 已构造完毕后引入 scoped_refptr 的安全方式。

  • 多线程/异步任务中合理组合这两者,是写好浏览器模块的重要实践技能。

相关文章:

  • 【OpenCV基础2】图像运算、水印、加密、摄像头
  • 如何在 Windows 11 或 10 上安装 FlutterFire CLI
  • CSS提高性能的方法有哪些
  • C++面试4-sizeof解析
  • RabbitMQ的简介
  • C 语言学习笔记(函数2)
  • AI在网络安全中的应用之钓鱼邮件检测
  • Python列表 vs 元组:全面对比解析(新手友好版)
  • MYSQL8.0常用窗口函数
  • input组件使用type=“number“的时候,光标自动跳到首位
  • 【Tools】VMware Workstation 17.6 Pro安装教程
  • 在 CentOS 7.9 上部署 node_exporter 并接入 Prometheus + Grafana 实现主机监控
  • PyMOL命令行和脚本
  • 精益数据分析(70/126):MVP迭代中的数据驱动决策与功能取舍
  • AI神经网络降噪 vs 传统单/双麦克风降噪的核心优势对比
  • 公网ip是固定的吗?动态ip如何做端口映射?内网ip怎么让外网远程访问?
  • 组态王通过开疆智能profinet转ModbusTCP网关连接西门子PLC配置案例
  • 学习BI---QuickBI介绍
  • ngx_http_scgi_module 技术指南
  • 问题 | 代码审查:函数是否包含返回语句
  • 首付款12.5亿美元!三生制药与辉瑞就国产双抗达成合作协议
  • 俄美元首通话超2小时,普京称愿与乌方共同起草和平备忘录
  • 家国万里·时光故事会|科学家伉俪,用玉米书写家国情怀
  • 刘小涛任江苏省委副书记
  • 查幽门螺杆菌的这款同位素长期被海外垄断,秦山核电站实现突破
  • 总奖金池百万!澎湃与七猫非虚构写作与现实题材征文大赛征稿启动