调度内部原理

主要观点:

  • 探讨多种实现并发的方式,如创建线程、异步 I/O、事件循环、抢占式和非抢占式调度器、栈式与无栈式等。
  • 分析各种方式的优缺点,如创建线程的问题(内存分配、性能等),异步 I/O 的适用场景和相关 API。
  • 介绍不同操作系统中的调度算法,如 Linux 的各种调度类(SCHED_FIFO、SCHED_RR、SCHED_DEADLINE、SCHED_OTHER 等)。
  • 讨论多核心情况下的调度策略,Go 中固定大小的单生产者多消费者队列等。

关键信息:

  • 创建线程存在内存分配粒度、性能、栈管理等问题,不适合大量并发任务。
  • 异步 I/O 可避免阻塞线程,通过非阻塞 socket 实现同时处理多个客户端,但存在 CPU 利用率高和代码复杂等问题。
  • 事件循环是一种高效的并发模型,通过异步 API 监控文件描述符,在事件准备好时执行回调。
  • 抢占式调度器通过定时器中断实现上下文切换,非抢占式调度器依赖程序员手动插入 yield 调用。
  • 栈式和无栈式实现协程各有优缺点,栈式与 OS 线程类似,无栈式常用于 async / await 语言特性。
  • 不同操作系统有不同的调度算法,适用于不同的场景,如 Linux 的各种调度类。
  • 多核心情况下需保证任务队列的线程安全性,Go 采用固定大小的单生产者多消费者队列并进行任务窃取。

重要细节:

  • 在 C 语言中实现简单的 echo 服务器,展示创建线程和异步 I/O 的方式及问题。
  • 介绍多种异步 I/O API,如 select、poll、epoll、aio、io_uring 等及其特点和适用平台。
  • libuv 为例说明事件循环的实现,以及在事件驱动开发中代码的特点和问题。
  • 通过代码示例展示非抢占式调度器的实现及存在的栈共享问题和修复方法。
  • 讲解 Go 中抢占式调度器的实现方式及相关监控线程。
  • 对比栈式和无栈式协程的实现及在不同语言中的应用。
  • 介绍 Linux 各种调度算法的特点和应用场景。
  • 提及 Go 中多核心调度的策略和 tokio 的借鉴。
阅读 59
0 条评论