面试题答案
一键面试1. 栈扩容情况及逻辑
- 扩容情况:
- 当Goroutine调用函数时,若栈空间不足以存放新的函数调用的局部变量和参数,就会触发栈扩容。
- 当进行深度递归调用,栈不断增长,达到当前栈容量上限时,也会触发扩容。
- 实现逻辑:
- 关键数据结构:
g
结构体,代表一个Goroutine,其中包含stack
字段,stack
结构体有lo
和hi
字段分别表示栈的起始和结束地址。m
结构体,代表一个操作系统线程,m
结构体中有curg
字段指向当前正在执行的Goroutine。
- 关键函数:
newstack
函数负责实际的栈扩容操作。当检测到栈空间不足时,会调用newstack
。它首先会分配一个新的、更大的栈空间,新栈大小通常是原栈大小的两倍。然后将原栈中的数据复制到新栈中,并调整相关的指针,比如更新g
结构体中stack
的lo
和hi
字段,以及栈指针等。同时,会将Goroutine的状态设置为Gcopystack
,表示正在进行栈复制操作。复制完成后,将状态改回Grunning
,继续执行Goroutine。
- 关键数据结构:
2. 栈缩容情况及逻辑
- 缩容情况:
- 在Goroutine运行过程中,如果栈空间使用量持续减少,远远低于当前栈容量,就有可能触发栈缩容,以节省内存。不过Go语言的栈缩容相对不那么频繁,因为频繁的缩容操作可能带来额外开销。
- 实现逻辑:
- 关键数据结构:与扩容类似,主要还是依赖
g
和m
结构体来跟踪Goroutine的栈信息。 - 关键函数:
- 栈缩容相关的核心函数是
shrinkstack
。当决定进行栈缩容时,shrinkstack
会先找到一个合适的新栈大小,一般是当前栈大小的一半,但需要满足一定的最小栈大小限制。然后分配新的较小的栈空间,将原栈中的活动数据复制到新栈,调整g
结构体中stack
的lo
和hi
字段以及栈指针,完成栈的缩容操作。同样,在操作过程中也会处理Goroutine状态的变化,以确保操作的原子性和正确性。
- 栈缩容相关的核心函数是
- 关键数据结构:与扩容类似,主要还是依赖