Sleeping/Waiting 个线程的上下文切换

Context Switches on Sleeping/Waiting Threads

我正在尝试了解操作系统如何处理不同模型中的上下文切换,以便更好地理解为什么 NIO 性能在请求数量出现大峰值的情况下更好。除了线程数量可能有限制之外,我很好奇在这些大量请求中执行的阻塞操作如何影响资源利用率。

在每线程一个请求的模型中,比如一个基于 servlet 2.5 的 Web 应用程序,如果 499 个线程正在等待数据库 IO 而只有一个线程需要工作,OS 上下文是否会在所有这 500 个线程之间切换试图找到需要工作的线程?要执行上下文切换,操作系统必须存储当前线程的状态,并恢复下一个线程的状态。这样做之后,OS 会发现它不需要任何 CPU 时间,并且会保持上下文切换,直到它找到需要工作的线程。 另外,这在服务器利用率方面是什么样的? CPU 是否很低,因为它主要受交换上下文的 IO 成本的限制,而不是实际计算任何东西?

在此先感谢您的帮助。如果你能给我指出书籍、教科书等方面的方向,我也将非常感激。

If 499 threads are waiting for database IO and only one thread needs work, does the OS context switch between all of those 500 threads trying to find the one that needs work?

如果 OS 的调度程序设计合理,则不会;一直迭代所有系统的线程将非常低效。

相反,大多数调度程序实现保留一个 sleeping/blocked 线程列表和一个单独的 "ready-to-run" 线程列表。当应该唤醒线程的事件发生时(例如,传入数据在套接字或文件句柄上变得可用,或者线程被阻塞的互斥体被释放),OS 将该线程从sleeping/blocked-线程列表到就绪线程列表。然后,当需要执行上下文切换时,OS 从就绪线程列表中选择一个线程,加载该线程的上下文,并启动它 运行。在任何 modern/popular OS 中,sleeping/blocked-threads-list 的大小对调度程序从准备就绪到 select 线程所花费的时间完全没有影响-线程列表到 运行。 (就绪线程列表的大小可能会产生影响,在某些 OS 下,但 some schedulers 的设计使得即使具有许多就绪线程的系统也不会导致调度程序效率降低)

Is the CPU low as it's mostly bound by the IO cost of swapping contexts in and out instead of actually computing anything?

假设您没有 运行 内存不足,则不会 I/O 涉及切换线程上下文;上下文切换仅涉及 CPU 和 RAM。如果 CPU 使用率低,最可能的原因是你的线程算法本身是 I/O 绑定的(例如,大多数东西都在等待你的网卡或硬盘驱动器读取或写入数据,大部分时间)。如果您的线程实际上没有执行任何操作 I/O,并且您仍然 I/O 受限,这可能表明您的计算机已用完所有可用 RAM,并且 thrashing -- 状态不好。