面试题答案
一键面试资源开销
- goroutine:
- 栈空间:初始栈空间很小,一般为2KB左右,随着需求动态增长和收缩,非常节省内存。例如一个简单的HTTP服务器,创建大量goroutine处理请求,因栈空间小,内存占用少。
- 其他开销:创建和销毁的开销极小,不需要像传统线程那样进行复杂的内核态与用户态切换等操作。
- 传统线程:
- 栈空间:栈空间一般固定且较大,通常为几MB,创建大量线程时会消耗大量内存。如一个多线程程序创建1000个线程,每个线程栈空间4MB,仅栈空间就消耗4GB内存。
- 其他开销:创建、销毁和上下文切换开销较大,涉及操作系统内核调度,需要进行用户态到内核态的切换等复杂操作。
调度方式
- goroutine:
- 由Go运行时(runtime)的调度器(GPM模型:G代表goroutine,P代表处理器,M代表操作系统线程)进行调度,属于协作式调度(又称非抢占式调度)。即一个goroutine在执行过程中主动让出CPU,如执行系统调用、I/O操作、调用
runtime.Gosched()
函数等。 - 调度在用户态进行,不涉及操作系统内核,调度速度快,上下文切换开销小。
- 由Go运行时(runtime)的调度器(GPM模型:G代表goroutine,P代表处理器,M代表操作系统线程)进行调度,属于协作式调度(又称非抢占式调度)。即一个goroutine在执行过程中主动让出CPU,如执行系统调用、I/O操作、调用
- 传统线程:
- 由操作系统内核调度,采用抢占式调度,操作系统根据线程的优先级、时间片等因素强制剥夺线程的CPU使用权。
- 上下文切换需要进入内核态,开销大,速度相对较慢。
创建数量限制
- goroutine:
- 由于资源开销小,理论上可创建数量非常多,轻松创建数以万计甚至更多。例如在一个网络爬虫程序中,可以创建几万甚至几十万的goroutine并发请求网页。
- 传统线程:
- 受系统资源(主要是内存,因每个线程栈空间大)限制,创建数量有限,一般在几千个左右。如果创建过多,可能导致系统内存耗尽,程序崩溃。