
go语言通过goroutine提供并发编程支持. Goroutine是go运行时库的功能,未由操作系统线程实现. Goroutine可以理解为用户模式线程.

由于goroutine由go运行时库管理,因此go运行时库还需要为每个goroutine创建和管理相应的堆栈空间. 为每个goroutine分配的堆栈空间不能太大,长时间打开goroutine会浪费很多空间. ,不能太小,会导致堆栈溢出. go语言选择堆栈的堆栈空间管理方式是在开始时提供相对小的空间,并根据需要自动增长. 当goroutine不需要那么多空间时,堆栈空间也应该自动缩小.
在进行1.3之前,请使用分段堆栈.

分段堆栈实现了可以继续增长的不连续堆栈. 一开始,堆栈只有一个段. 当需要更多堆栈空间时,将分配一个新段,并且先前的堆栈将被双向链接. 这样,堆栈由多个双向链接的段组成. 新分配的段用完后,新段将被释放.

分段堆栈实现了堆栈的按需收缩,并且在添加新分段时无需复制原始分段中的数据,这使得goroutine的使用非常便宜.
分段堆栈的优点是它可以根据需要增长并且空间利用率相对较高. 但是,分段堆栈在某些情况下也具有某些缺陷. 当某个段将要用完时,使用for循环执行一个占用空间的函数将使goroutine在执行该函数时分配该段,并在执行返回时销毁该段,以使其出现在环. 堆栈的多次伸缩会导致很大的性能损失. 这种情况称为堆栈拆分(Stack Split).

Go 1.3引入了连续堆栈. 连续堆栈使用另一种策略. 它不再将堆栈分成多个部分. 当堆栈空间不足时,它将直接创建一个两倍大的堆栈空间,并放置原始堆栈空间. 数据被复制到新的堆栈空间,然后旧的堆栈被破坏. 这样栈空间栈空间,当堆栈空间接触边界时,就不会发生堆栈拆分.
继续假定当前堆栈空间将要用完,并且需要在for循环中执行更多空间消耗函数. 执行该函数时,堆栈空间将扩展并变为原始大小的两倍. 函数执行一次后,堆栈空间量将减少到执行前的大小,但是堆栈空间量不少于1/4,不会触发堆栈收缩,因此在整个for循环执行期间,不会反复触发堆栈空间的缩小和扩展.
与分段堆栈相比,连续堆栈避免了在某些情况下频繁缩放堆栈空间的情况. 需要注意的一件事是,连续堆栈的缩小还需要重新应用一定的空间(原始的1/2大小)并执行堆栈复制操作.
点击关注以了解Golang私房菜列
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-203595-1.html
敢进领海一个毫米就打你个满地找牙