noh*_*hup 6 multithreading pthreads go coroutine goroutine
如果这个问题太愚蠢,请道歉.我是通过够程的细节阅读这里.根据那个页面,它说Goroutines are multiplexed onto a small number of OS threads, rather than a 1:1 mapping,我所能想到的只有我有限的知识是,产生的OS线程数量有限,其中可能使用用户空间线程或协同程序.它是否正确?如果是这样,如果我可以举一个例子,如果一个程序克隆4个OS线程,其中有多个用户空间线程,并且在所有这4个线程中发生了单个阻塞操作以及非阻塞操作,那么操作系统scheduler context-switch所有这些线程,因为用户空间线程对OS线程不透明?
出于好奇,是否有可能实现goroutines的C实现,这有助于理解内部结构?
Goroutines 在所谓的“逻辑处理器”(不是物理处理器)中运行。每个逻辑处理器都绑定到单个操作系统线程。
Go 1.5之后,逻辑处理器的数量等于可用物理处理器的数量。
Go调度器智能地调度多个goroutine在每个逻辑处理器上的运行
粗略图如下:-
操作系统线程 ------ 逻辑处理器 ------ Goroutine 1, Goroutine 2..... Goroutine n
现在,其中一个 Goroutines 很可能会进行阻塞系统调用。当这个情况发生时,
进行阻塞调用的操作系统线程和 Goroutine 与逻辑处理器分离
该逻辑处理器现在没有操作系统线程。
Go 调度程序创建一个新的操作系统线程,并将其附加到逻辑处理器。附加到逻辑处理器的剩余 goroutine 现在继续运行。
分离的 goroutine 及其关联的操作系统线程继续阻塞,等待系统调用返回。
当系统调用返回时,goroutine 重新附加到逻辑处理器之一,并放入其运行队列中。
操作系统线程被“搁置以供将来使用”。我猜它被添加到某种线程池中。
如果 goroutine 进行网络 I/O 调用,则处理方式略有不同。
Goroutine 与逻辑处理器分离,并移至集成网络轮询器。一旦轮询器表明 I/O 操作已准备好,goroutine 就会重新连接到逻辑处理器来处理它。
-- 现在,回答你的问题:-)
我不是专家,但根据上述内容,我认为将会发生这种情况。
由于 4 个操作系统线程中的每一个上的一个 goroutine 都进行了阻塞系统调用,因此所有 4 个线程都将与其逻辑处理器分离,并且将继续阻塞,直到系统调用返回。4 个操作系统线程将与进行阻塞系统调用的各自 goroutine 相关联。
现在,这会产生 4 个逻辑处理器(以及附加到它们的非阻塞 goroutine),而没有任何操作系统线程。
因此,GO 调度程序创建 4 个新的操作系统线程,并将逻辑处理器分配给这些线程。
--
从操作系统的角度来看,显然不能允许进行阻塞调用的 4 个操作系统线程占用 CPU 时间,因为它们没有执行任何操作。
因此,它将与其选择的其他非阻塞线程切换上下文。
| 归档时间: |
|
| 查看次数: |
404 次 |
| 最近记录: |