解释一下Go work stealing 机制?

Go的运行时系统使用了一种名为 “Work Stealing”(工作窃取)的调度策略来分配Goroutine到可用的线程(在Go中,这些线程被称为M,即Machine)上执行。

Go的调度器使用了P(Processor)与M和Goroutine进行交互。每个P都维护了一个本地的Goroutine队列,新创建的Goroutine首先会被放入创建它的P的本地队列中。在这个系统中,P可以看作是可调度Goroutine的数量,每个P都可以关联一个M来执行Goroutine。

“Work Stealing”策略的工作原理如下:

  1. 当一个M完成了当前的Goroutine后,它会首先检查与它关联的P的本地队列,如果队列中还有Goroutine,就取出一个来执行。

  2. 如果本地队列已经为空,M会尝试从其他P的队列中”窃取”一个Goroutine来执行,这就是所谓的”Work Stealing”。

  3. 如果所有的P的队列都为空,M就会进入一个全局的队列中等待,直到有新的Goroutine被创建。

“Work Stealing”机制能够确保所有的P和M都能尽可能地保持忙碌,从而充分利用多核处理器的计算能力。同时,由于每个P都尽可能地使用本地队列中的Goroutine,这也减少了线程间的同步开销。

以下是一个简化的示意图,展示了P、M和Goroutine如何交互:

     P1       P2       P3
     |        |        |
     v        v        v
    [G1,G2] [G3]   [G4,G5,G6] 
     ^        ^        ^
     |        |        |
     M1       M2       M3

在这个图中,我们有3个P(P1、P2和P3),每个P都有一个本地的Goroutine队列。M1、M2和M3是3个线程,每个线程都关联了一个P,并且从其队列中取出Goroutine来执行。当M1完成了G1后,它会从P1的队列中取出G2来执行。如果P1的队列为空,M1就会尝试从P2或P3的队列中”窃取”一个Goroutine。

发表评论

后才能评论