面试题答案
一键面试- 工作原理概述:
- Go语言的调度器采用M:N调度模型,即多个Goroutine映射到多个操作系统线程(M)上。它主要由G(Goroutine)、M(Machine,操作系统线程)、P(Processor,逻辑处理器)三部分组成。P管理着一个本地G队列,M从P的本地队列或全局队列中获取G来执行。
- Goroutine执行系统调用时调度器操作:
- 让出M:
- 当一个Goroutine执行系统调用时,它会将所在的M与P分离。这是因为系统调用通常会阻塞操作系统线程,若不分离,会导致整个P上的其他Goroutine都无法执行。例如,当Goroutine执行文件读取的系统调用时,这个操作可能会等待磁盘I/O完成,在等待期间,如果不分离M和P,P上其他可运行的Goroutine(如处理网络请求的Goroutine)就会被阻塞。
- 让出M后,调度器会寻找一个空闲的M(如果有),让其与当前P绑定继续执行P本地队列中的其他Goroutine。若没有空闲的M,调度器会创建一个新的M来与P绑定。
- 将Goroutine放入等待队列:
- 执行系统调用的Goroutine会被放入与该系统调用相关的等待队列中。例如,如果是网络I/O的系统调用,该Goroutine会被放入网络I/O等待队列。当系统调用完成(如磁盘I/O操作结束、网络数据可读等),相关的事件通知机制会将该Goroutine重新放回P的本地队列或者全局队列(具体取决于实现细节和调度器策略),等待被调度执行。
- 调度其他Goroutine:
- 在让出M且执行系统调用的Goroutine被放入等待队列后,调度器会从P的本地队列或全局队列中选择其他可运行的Goroutine,让M去执行它们。这样就保证了在一个Goroutine执行系统调用阻塞期间,其他Goroutine仍然可以在M上运行,从而提高了并发性能和资源的有效利用率。例如,在一个包含多个Goroutine的程序中,一个Goroutine在进行长时间的数据库查询(系统调用)时,其他Goroutine可以继续处理HTTP请求等任务。
- 让出M: