Goroutine(协程)是 Go 语言中的轻量级线程,它们由 Go 运行时负责调度和管理。Goroutine 的调度模型与传统的线程调度模型有所不同,它采用了 M:N 调度模型,其中 M 个 goroutine 会被映射到 N 个系统线程上进行执行。
在这种调度模型中,每个系统线程都有一个本地调度器(LTS)来管理 goroutine 的调度和执行。LTS 会从全局运行队列中获取 goroutine,并将其放入线程本地的运行队列中。每个 goroutine 在执行时,都有可能会发生阻塞或者休眠的情况,比如等待 I/O 完成、等待锁的释放、调用 time.Sleep 等。这时候,LTS 就会把这个 goroutine 移除出线程本地的运行队列,并将其放入等待队列中,等待阻塞的事件完成后再重新将其放入运行队列中。
当一个 goroutine 需要创建另一个 goroutine 时,它会在当前线程的本地运行队列中找到一个空闲的 P(processor),并将其分配给新创建的 goroutine 进行执行。如果当前线程本地的运行队列中没有空闲的 P,则会从全局运行队列中获取一个空闲的 P,并将其绑定到当前线程上。
通过这种 M:N 的调度模型,Go 语言可以在高并发的场景下更高效地利用系统资源,并且能够更好地处理 I/O 密集型任务和计算密集型任务。同时,由于 goroutine 的启动和销毁比线程更加轻量级,因此可以更快速地响应高并发的请求。