等待 IO 的线程是不是也会阻塞核心?

Posted

技术标签:

【中文标题】等待 IO 的线程是不是也会阻塞核心?【英文标题】:Does a thread waiting on IO also block a core?等待 IO 的线程是否也会阻塞核心? 【发布时间】:2016-06-11 20:13:48 【问题描述】:

在同步/阻塞计算模型中,我们通常说执行线程会在等待 IO 任务完成时等待(阻塞)。

我的问题是这通常会导致执行线程的 CPU 内核空闲,还是等待 IO 的线程通常会被上下文切换并进入等待状态,直到 IO 准备好被处理?

【问题讨论】:

【参考方案1】:

对于大多数以标准方式使用的编程语言,答案是它会阻塞你的线程,但不会阻塞你的 CPU。

您需要为 1 个线程显式地为特定线程(亲和性)保留一个 CPU 以阻塞整个 CPU。要更明确,请参阅此question:

您可以在除您的进程之外的每个进程上调用 SetProcessAffinityMask,并使用一个掩码,该掩码仅排除将“属于”您的进程的核心,并在您的进程中使用它来将其设置为仅在该核心上运行(或者,甚至更好, SetThreadAffinityMask 仅在执行时间关键任务的线程上)。

【讨论】:

Affinity 与此相反:它将线程标记为只能在有限的一组 CPU 上运行。它不会阻止其他任务使用该 CPU。最近有一个问题,关于如何为一个进程预留一个core,但是找不到。 您可以使用亲和性来排除其他进程在线程运行的核心上运行。 @DevShark 您正在考虑使用 CPU 亲和力 + isolcpus(例如在 Linux 中)【参考方案2】:

CPU 内核通常不专用于一个特定的执行线程。内核不断地切换正在执行的进程进出 CPU。 CPU当前正在执行的进程处于“运行”状态。等待轮到它们的进程列表处于“就绪”状态。内核非常快速地切换这些输入和输出。现代 CPU 功能(多核、同时多线程等)试图增加可以一次物理执行的执行线程数。

如果一个进程被 I/O 阻塞,内核只会将它放在一边(将其置于“等待”状态),甚至不会考虑在 CPU 中给它时间。当 I/O 完成后,内核将阻塞的进程从“等待”状态移动到“就绪”状态,以便它可以在 CPU 中轮到(“运行”)。

所以你阻塞的执行线程只会阻塞:执行线程。 CPU 和 CPU 内核继续让其他执行线程进出它们,并且不会空闲。

【讨论】:

@RyanVincent:用户空间进程可以直接使用内存,而无需进行系统调用。 A process waiting on cache misses is still tying up a CPU core。如果使用忙等待自旋锁进行线程同步也是如此。当等待其他任何事情时,内核将收到通知。它将唤醒正在等待该磁盘块或网络数据包的线程。 另外,Linux 上的低优先级任务总是获得一些 CPU。最小优先级不是“仅当 CPU 空闲时”,以避免在低优先级进程占用资源或其他东西时出现死锁。显然,支持真正的空闲优先级会使调度程序更加复杂,因为它必须检查何时可以安全地完全饿死一个进程。所以即使不使用它也会稍微减慢调度,因此 Linux 不包含它。所以每个没有等待的进程都会收到一些时间片。 @PeterCordes,感谢您的解释 - 它有帮助。【参考方案3】:

如果我们假设它不是异步的,那么我会说,在这种情况下,拥有该线程的线程肯定会被放入等待队列,并且状态将是“等待”。

上下文切换明智,IMO,它可能需要更多解释,因为术语上下文切换可能意味着/涉及许多事情(换入/换出、页表更新、寄存器更新等)。根据当前的执行状态,可能会安排属于同一进程的第二个线程运行,而在 IO 操作上被阻塞的线程仍在等待。

例如,上下文切换很可能仅限于更改 CPU 上与内核有关的寄存器值(但如果剩余内存不多,拥有的进程甚至可能被换出)。

【讨论】:

【参考方案4】:

不,在java中,块线程不参与调度

【讨论】:

以上是关于等待 IO 的线程是不是也会阻塞核心?的主要内容,如果未能解决你的问题,请参考以下文章

Java NIO使用

Java NIO使用

IO概念解析------同步异步阻塞非阻塞

004---IO模型

IO模型

java Future 阻塞