线程模型有哪些?为什么 Go Scheduler 需要实现 M:N 的方案?Go Scheduler 由哪些元素构成呢?

线程模型主要有以下三种:

  1. 1:1模型:每一个用户级线程对应一个内核级线程。这是许多操作系统,包括Linux和Windows,所采用的模型。但是,创建和销毁内核级线程,以及线程上下文切换的开销都相对较大,且内核级线程占用的资源较多。

  2. N:1模型:多个用户级线程对应一个内核级线程。这种模型可以支持大量用户级线程,因为用户级线程比内核级线程轻量。但是,这种模型的一个主要问题是,一旦一个用户级线程开始执行系统调用,整个内核级线程都会被阻塞,导致其他所有用户级线程都无法执行。

  3. M:N模型:多个用户级线程对应多个内核级线程。这种模型结合了前两种模型的优点。它可以通过调度器在用户级线程和内核级线程之间进行映射,从而支持大量的用户级线程,同时还能利用多核处理器的并行处理能力。

Go语言选择实现M:N的线程模型,因为它可以支持大量的goroutine(用户级线程),同时还能有效地利用多核处理器,并且对于系统调用和阻塞操作有良好的处理。

Go的调度器(Scheduler)主要由以下几个元素构成:

  • M(Machine):代表一个内核线程。M负责执行代码,并且拥有执行代码所必需的资源,比如栈、寄存器等。

  • P(Processor):代表一个逻辑处理器。P保存了运行goroutine所需的资源,并且管理着一组goroutine。每个P都会关联一个M,M在P上执行P的goroutine队列中的goroutine。

  • G(Goroutine):代表一个goroutine。每个G都有自己的栈和程序计数器。

在运行时,每个P都会选择一个G,然后在关联的M上执行这个G。当G阻塞时,P会选择另一个G来执行。当所有的G都阻塞时,P会让出M,让其他的P使用。这样,Go的调度器就能够在用户级别进行调度,同时还能有效地利用多核处理器。

发表评论

后才能评论