Go的运行时系统使用了一种名为Work Stealing
(工作窃取)的调度策略来分配Goroutine到可用线程(称为M
,即Machine)上执行。这样可以最大化CPU使用率,减少任务调度的开销。在这种机制下,任务队列和调度器通过动态平衡负载来提高并发性能和吞吐量。
Go的调度器使用了P(Processor)与M和Goroutine进行交互。每个P都维护了一个本地的Goroutine队列,新创建的Goroutine首先会被放入创建它的P的本地队列中。在这个系统中,P可以看作是可调度Goroutine的数量,每个P都可以关联一个M来执行Goroutine。
基本工作原理
-
任务队列:每个工作线程(或goroutine)都有自己的双端队列(deque),用于存储任务。当一个线程生成新任务时,它会将任务放入自己的队列。这种队列就是上述所讲的P处理器。
-
执行任务:M首先从自己对应P中获取任务并执行。如果它的任务队列为空,它就会尝试从其他线程的任务队列P中窃取任务。
-
窃取任务:当一个M发现自己的任务队列P为空时,它会随机选择其他M的任务队列P,从队列的另一端窃取任务。这样可以避免竞争,因为线程对自己的任务队列使用一端,而其他线程只能从另一端窃取任务。
-
负载均衡:通过这种机制,系统能够动态地平衡负载。如果某个线程的任务较多,其他空闲线程可以帮助处理这些任务,从而避免某些线程过载而