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

主从IO核心

问:你的意思是每个线程都有自己的一个事件循环EventLoop,主线程有,工作线程也有。主线程来处理定时器事件,新事件的连接,已连接事件的读写,,我能理解它需要事件循环去轮询(每隔一段时间返回要处理的channel),但是工作线程为什么也要事件循环,工作线程不就是处理主线程给他分配的任务吗,请你讲讲主线程给工作线程分配了什么任务,在哪个类中分配的(结合muduo源码告诉我),工作线程为什么也要事件循环,越详细越好,还要通俗易懂

在 muduo 的“One Loop Per Thread”模型中,工作线程的事件循环(EventLoop)是处理已建立连接所有 I/O 操作的核心引擎,而不仅仅是执行普通计算任务。下面结合源码详细解释其设计逻辑和工作原理:


一、主线程给工作线程分配什么任务?

主线程(Main Reactor)通过 EventLoopThreadPool 类将 已建立的 TCP 连接 分配给工作线程(Sub Reactor)。具体流程如下:

  1. 主线程接受新连接
    主线程的 Acceptor 监听端口,当有新连接时创建 TcpConnection 对象。

  2. 选择工作线程
    通过轮询算法(Round Robin)从线程池中选择一个工作线程的 EventLoop

    cpp

    // TcpServer.cc
    void TcpServer::newConnection(int sockfd, const InetAddress& peerAddr) {EventLoop* ioLoop = threadPool_->getNextLoop(); // 轮询选择子ReactorTcpConnectionPtr conn = std::make_shared<TcpConnection>(ioLoop, ...);ioLoop->runInLoop(std::bind(&TcpConnection::connectEstablished, conn));
    }
  3. 跨线程投递任务
    ioLoop->runInLoop() 将 TcpConnection::connectEstablished 方法异步投递到工作线程的任务队列中,唤醒工作线程处理69。


二、工作线程为什么需要事件循环?

工作线程的事件循环负责处理两类任务,需持续监听事件:

1. 处理连接的 I/O 事件
  • 每个 TcpConnection 绑定到一个工作线程后,其对应的 Channel(封装 socket fd)会注册到该线程的 Poller 上。

  • 工作线程的 EventLoop::loop() 调用 epoll_wait 监听这些 fd 的读写事件:

    cpp

    // EventLoop.cc
    while (!quit_) {activeChannels_.clear();poller_->poll(..., &activeChannels_); // 监听I/O事件for (Channel* channel : activeChannels_) {channel->handleEvent(); // 处理数据到达、发送等}
    }
  • 例如:当客户端发送数据时,工作线程的 Poller 返回活跃的 Channel,触发 TcpConnection::handleRead() 读取数据16。

2. 执行跨线程投递的任务
  • 当主线程或其他线程调用 runInLoop() 时,任务会被加入工作线程的待执行队列 pendingFunctors_

  • 工作线程在每轮事件循环的末尾执行这些任务:

    cpp

    void EventLoop::doPendingFunctors() {std::vector<Functor> functors;{std::lock_guard<std::mutex> lock(mutex_);functors.swap(pendingFunctors_); // 取出任务}for (const auto& functor : functors) {functor(); // 执行任务(如TcpConnection的初始化)}
    }
  • 例如:主线程投递的 TcpConnection::connectEstablished 会在此执行,将连接注册到工作线程的 Poller69。


三、关键类的协作关系

类名职责关键方法
EventLoopThreadPool管理线程池,分配连接给子ReactorgetNextLoop() 轮询选择子Reactor
EventLoopThread创建线程并运行其 EventLoopstartLoop() 启动线程,threadFunc() 创建事件循环
EventLoop执行事件循环,处理I/O事件和跨线程任务loop()runInLoop()queueInLoop()
TcpConnection封装连接,所有操作必须在绑定线程中执行send()connectEstablished()(通过 runInLoop 确保线程安全)

四、通俗理解:工作线程事件循环的作用

类比 工厂生产线

  1. 主线程(厂长)
    接收新订单(接受连接),将订单分配给某条生产线(工作线程)。

  2. 工作线程事件循环(生产线)

    • 监控原材料运输(I/O 事件)
      流水线工人(Poller)持续检查是否有货物到达(数据可读)或需要发货(数据可写)。

    • 处理厂长指令(跨线程任务)
      厂长通过广播(wakeupFd_)通知生产线:“有新订单分配给你!”(投递 TcpConnection),工人立即处理。

若工作线程没有事件循环:

  • 无法主动监听连接的数据到达,只能被动等待主线程通知(效率低下)。

  • 无法保证连接的所有操作(读/写/关闭)在同一线程执行,需加锁保护(性能损耗)。


五、性能优势

  1. 无锁设计:每个连接的 I/O 操作仅在一个线程内完成,避免竞争59。

  2. 高吞吐量

    • 工作线程直接处理 I/O 事件,无任务派发延迟。

    • 多核 CPU 可并行处理多个连接的 I/O(如 8 核可运行 8 个工作线程)5。

  3. 与计算线程池分离
    muduo 额外提供 ThreadPool 处理计算密集型任务(如数据库查询),防止阻塞 I/O 线程85。


六、总结

工作线程的事件循环是 muduo 高性能的核心机制

  1. 任务类型:处理已分配连接的 I/O 事件(如读写数据)和 跨线程投递的任务(如连接初始化)。

  2. 事件循环必要性

    • 监听 socket 事件需持续运行 epoll_wait

    • 确保连接的所有操作在绑定线程执行,避免锁竞争。

  3. 源码协作
    主线程通过 EventLoopThreadPool 分配连接,通过 runInLoop() 唤醒工作线程执行任务。工作线程的 EventLoop::loop() 同时处理 I/O 事件和任务队列。

  4. ℹ️ 完整流程可参考 TcpServer::newConnection 和 EventLoop::doPendingFunctors 源码。

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

相关文章:

  • Transformers 和 PyTorch 的区别与安装指南
  • Flowable23手动、接收任务----------持续更新中
  • 【计算机基础理论知识】C++篇(二)
  • codeforeces Round1032 - Round 1036
  • 学习笔记(32):matplotlib绘制简单图表-数据分布图
  • Linux Vim 编辑器详解:从入门到进阶(含图示+插件推荐)
  • Java从入门到精通!第三天(数组)
  • 【threejs】第一人称视角之八叉树碰撞检测
  • 论文笔记(LLM distillation):Distilling Step-by-Step!
  • MiniGPT4源码拆解——models
  • 原生微信小程序研发,如何对图片进行统一管理?
  • 微信小程序101~110
  • UnrealEngine5游戏引擎实践(C++)
  • Android Coil 3 data加载图的Bitmap或ByteArray数据类型,Kotlin
  • Android 如何阻止应用自升级
  • C语言 | 函数核心机制深度解构:从底层架构到工程化实践
  • Matplotlib 全面使用指南 -- 自动缩放坐标轴 Autoscaling Axis
  • 【Linux】Linux 操作系统 - 27 , 进程间通信(三) --System V 共享内存
  • 编写bat文件自动打开chrome浏览器,并通过selenium抓取浏览器操作chrome
  • 抽象类基础知识
  • 如何选择合适的ai降重工具?七个实用的ai查重网站
  • 【会员专享数据】2013-2024年我国省市县三级逐日SO₂数值数据(Shp/Excel格式)
  • 告别繁琐:API全生命周期管理的新范式——apiSQL
  • 调用京东API接口时,如果超过了调用频率限制,应该如何处理?【项目经验分享】
  • Django+DRF 实战:自定义异常处理流程
  • FeatherScan v4.0 – 适用于Linux的全自动内网信息收集工具
  • 快速搭建服务器,fetch请求从服务器获取数据
  • linux网络编程之读缓冲区设计
  • 系统性部署系统母盘【rhel7和rhel9】
  • 腾讯云分为几个区域