GoLang之goroutine和线程的区别(1)

本文探讨了Go语言中的goroutine与线程的主要区别,包括内存占用(goroutine仅为2KB,线程为1MB),创建销毁(goroutine由Goruntime高效管理,线程涉及内核交互),以及切换成本(goroutine仅需保存少量寄存器,线程切换昂贵)。这些特性使得goroutine在高并发场景下更具优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GoLang之goroutine和线程的区别

谈到 goroutine,绕不开的一个话题是:它和 thread 有什么区别?

我们可以从三个角度区别:内存消耗、创建与销毀、切换。

1.内存占用

创建一个 goroutine 的栈内存消耗为 2 KB,实际运行过程中,如果栈空间不够用,会自动进行扩容。创建一个 thread 则需要消耗 1 MB 栈内存,而且还需要一个被称为 “a guard page” 的区域用于和其他 thread 的栈空间进行隔离。

对于一个用 Go 构建的 HTTP Server 而言,对到来的每个请求,创建一个 goroutine 用来处理是非常轻松的一件事。而如果用一个使用线程作为并发原语的语言构建的服务,例如 Java 来说,每个请求对应一个线程则太浪费资源了,很快就会出 OOM 错误(OutOfMemoryError)。

2.创建和销毀

Thread 创建和销毀都会有巨大的消耗,因为要和操作系统打交道,是内核级的,通常解决的办法就是线程池。而 goroutine 因为是由 Go runtime 负责管理的,创建和销毁的消耗非常小,是用户级。

3.切换

当 threads 切换时,需要保存各种寄存器,以便将来恢复:

16 general purpose registers, PC (Program Counter), SP (Stack Pointer), segment registers, 16 XMM registers, FP coprocessor state, 16 AVX registers, all MSRs etc.

而 goroutines 切换只需保存三个寄存器:Program Counter, Stack Pointer and BP。

一般而言,线程切换会消耗 1000-1500 纳秒,一个纳秒平均可以执行 12-18 条指令。所以由于线程切换,执行指令的条数会减少 12000-18000。

Goroutine 的切换约为 200 ns,相当于 2400-3600 条指令。因此,goroutines 切换成本比 threads 要小得多。

### Goroutine 的详细介绍 Goroutine 是 Go 语言中的轻量级线程,由 Go 运行时环境管理调度。相比操作系统级别的线程Goroutine 更加轻便,启动成本低,适合大规模并发操作[^1]。 #### 创建与基本用法 要创建一个新的 Goroutine 只需在函数前加上 `go` 关键字即可让该函数异步执行: ```go func say(s string) { for i := 0; i < 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(s) } } func main() { go say("world") // 启动一个新goroutine来运行say函数 say("hello") } ``` 这段代码展示了如何在一个新的 Goroutine 中调用 `say()` 函数,并继续执行主线程中的其他逻辑。 #### 参数传递方式 可以像普通函数一样向 Goroutine 传递参数,需要注意的是如果传递指针作为参数,则应确保所指向的对象不会被过早释放或者修改造成数据竞争问题。 #### 同步机制 为了安全地共享资源以及控制多个 Goroutine 执行顺序,Go 提供了多种同步原语如 Channel WaitGroup 来协调它们之间的协作关系。 ### 使用场景分析 由于 Goroutine 轻量化特性,在 I/O 密集型任务(网络请求、文件读取)、CPU 并发计算等方面表现出色。特别是在 Web 开发领域,对于高并发 HTTP 请求处理尤为适用[^4]。 例如面对海量 API 接口访问需求时,可以通过开启大量 Goroutine 实现快速响应;而在批处理作业中也能有效提升整体吞吐率。 ### 最佳实践总结 尽管 Goroutine 功能强大但也存在一些潜在风险点需要注意: - **避免滥用 ID**: 自 Go 1.4 版本之后官方不再支持直接获取 Goroutine ID ,主要是防止误用此功能实现类似于线程局部存储 (Thread Local Storage),这会增加 GC 压力并影响性能表现[^2]. - **合理规划数量**: 尽管单个 Goroutine 占用资源较少但仍需谨慎设定最大并发数以免耗尽系统资源引发 OOM 错误[^3]. - **编写可测试代码**: 设计易于单元测试的并发结构有助于提高软件质量减少调试难度. - **关注生命周期管理**: 对于长时间存活的任务建议采用上下文(Context)模式以便能够优雅退出或超时取消正在运行的操作.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GoGo在努力

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值