2 回答
TA贡献1798条经验 获得超3个赞
"
go
" 语句开始执行作为独立并发控制线程的函数调用,或者goroutine
,在同一地址空间内。有人可以向我解释问题的基本原理吗?
“地址空间”是一个通用术语,可应用于多种情况:
地址空间是通过组合足够多的唯一标识限定符来创建的,以使地址明确(在特定地址空间内)
Dave Cheney的演讲“让 Go 变得更快的五件事”说明了在同一进程地址空间中使用 goroutine 解决的主要问题:堆栈管理。
Dave's 限定了“地址空间”,首先谈到线程:
因为进程切换可以在进程执行的任何时候发生,操作系统需要存储所有这些寄存器的内容,因为它不知道当前正在使用哪些寄存器。
这导致了线程的发展,线程在概念上与进程相同,但共享相同的内存空间。
(所以这是关于内存的)
然后 Dave 说明了进程地址空间(由进程管理的地址)内的堆栈:
传统上在进程的地址空间内,
堆位于内存的底部,就在程序(文本)上方并向上增长。
堆栈位于虚拟地址空间的顶部,并向下增长。
另请参阅“堆栈和堆是什么以及在哪里? ”。
问题:
因为堆和栈相互覆盖将是灾难性的,操作系统通常会安排在栈和堆之间放置一个不可写的内存区域,以确保如果它们确实发生冲突,程序将中止。
对于线程,这可能会导致限制进程的堆大小:
随着程序中线程数量的增加,可用地址空间的数量会减少。
goroutine 使用不同的方法,同时仍然共享相同的进程地址空间:
那些 goroutine 的堆栈要求呢?
Go 编译器不使用保护页,而是在每个函数调用中插入检查,以检查是否有足够的堆栈供函数运行。如果没有,运行时可以分配更多的堆栈空间。
由于这种检查,goroutines 的初始堆栈可以变得更小,这反过来又允许 Go 程序员将 goroutines 视为廉价资源。
Go 1.3 引入了一种管理这些堆栈的新方法:
如果 goroutine 的堆栈太小,将分配一个新的、更大的堆栈,而不是添加和删除额外的堆栈段。
旧堆栈的内容被复制到新堆栈,然后 goroutine 继续使用新的更大的堆栈。
在第一次调用 H 之后,堆栈将足够大,因此对可用堆栈空间的检查将始终成功。
TA贡献1836条经验 获得超4个赞
当您的应用程序在 RAM 上运行时,RAM 中的地址由内存管理器分配给您的应用程序。这称为地址空间。
概念:
处理器 (CPU) 在 Fetch-Decode-Execute 循环中执行指令。它通过将指令提取到 RAM(随机存取存储器)来执行应用程序中的指令。这样做是因为从磁盘一路获取它的效率非常低。有人需要跟踪内存使用情况,因此操作系统实现了内存管理器。您的应用程序由一些程序组成,在您的情况下,这是用 Go 编程语言编写的。当您执行脚本时,操作系统以上述方式执行指令。
看了你的帖子,感同身受。随着程序的增多,你提到的术语会变得越来越熟悉。
我第一次从操作系统书(又名恐龙书)中遇到这些术语。
希望这对你有帮助。
- 2 回答
- 0 关注
- 186 浏览
添加回答
举报