Goroutine是什么
Golang的一大特色就是他原生支持高并发。高并发这件事,即使是慢如Python也是可以应付的,为什么Golang在这方面如此“出彩”呢。
因为他从关键字层面实现了多协程开发。
实现并发的一大因素就是Goroutine,在一个Go程序中,我们如何创建一个Goroutine呢,非常简单
go f()
就这样,我们创建了一个Goroutine,值得注意的是,Goroutine不同于传统意义上的线程或是协程,他兼顾了两者的优点。
Goroutine 的调度原理
Goroutine 的调度由 Go 语言的运行时 (runtime) 负责,这种调度机制通常被称为 M
模型。
- M模型:这种模型指的是 M 个 Goroutine 运行在 N 个操作系统线程上。Go 语言的运行时通过调度器将多个 Goroutine 映射到少量的系统线程上运行,从而实现高效的并发处理。
具体实现细节
-
Goroutine:
- 每个 Goroutine 都有自己的栈空间,初始栈很小(通常是 2KB),并且可以根据需要动态增长。这使得 Goroutine 相比于传统线程更加轻量,不会浪费大量的内存。
-
P (Processor):
-
Go 运行时引入了“P”的概念,表示逻辑处理器。P 是运行 Goroutine 所需的资源,它管理了 Goroutine 队列。在默认情况下,P 的数量等于可用 CPU 核心数,可以通过环境变量
GOMAXPROCS
设置。 -
每个 P 都会被绑定到一个操作系统线程上,当线程运行时,P 会从自己的 Goroutine 队列中取出 Goroutine 执行。
-
-
M (Machine):
-
M 代表一个操作系统线程,负责执行 P 上的 Goroutine。每个 M 只能绑定一个 P,但 P 可以切换绑定到不同的 M 上。
-
当 M 运行一个 Goroutine 时,如果 Goroutine 因为系统调用或其他原因阻塞,P 会解除与该 M 的绑定,并寻找一个空闲的 M 来继续运行队列中的其他 Goroutine。
-
-
调度器:
-
Go 的调度器负责管理 G (Goroutine), P (Processor), 和 M (Machine) 之间的关系。当一个 Goroutine 被创建时,它会被放入到 P 的本地队列中。调度器定期检查并决定哪个 Goroutine 应该被运行,以及如何将 P 和 M 进行最优匹配。
-
当一个 Goroutine 阻塞时,调度器会尝试将其他的 Goroutine 安排到不同的线程上执行,避免 CPU 闲置。
-
-
抢占式调度:
- Goroutine 的调度是抢占式的,这意味着运行时可以在合适的时间点强制中断 Goroutine 的执行并调度其他的 Goroutine 运行。Go 运行时会定期检查 Goroutine 的运行时间,如果某个 Goroutine 运行过久,就会被强制挂起以便其他 Goroutine 获得执行机会。
Goroutine的好处
在其他语言,我们要实现高并发,那就比如要手动调整线程,协程的运行逻辑,或者引入相关的库,耗时耗力而且效果不一定是最好。Goroutine的调度细节完全由运行时决定,大大降低了调度难度,而且由于是原生支持的,效率还更高
Channel
Go 语言中的通道(channel)是用于在不同的 goroutine 之间进行通信和同步的核心机制。可以理解为一个管道,信息可以从管道的这一头传送到管道的另一头。在Golang里面强调每个Goroutine之间应该采用互相发消息的形式而不是共享内存的形式
通道的实现涉及到复杂的底层数据结构和同步原语。以下是对 Go 语言中通道实现的简要概述:
通道的基本概念
-
无缓冲通道:发送操作会阻塞,直到有接收操作为止,反之亦然。
-
带缓冲通道:发送操作在缓冲区未满时不会阻塞,接收操作在缓冲区非空时不会阻塞
Example
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int, 2) // 创建一个带缓冲的通道
// 启动一个发送者 goroutine
go func() {
for i := 0; i < 5; i++ {
ch <- i
fmt.Println("Sent:", i)
time.Sleep(time.Second)
}
close(ch) // 关闭通道
}()
// 启动一个接收者 goroutine
go func() {
for v := range ch {
fmt.Println("Received:", v)
}
}()
// 等待一段时间,确保所有操作完成
time.Sleep(10 * time.Second)
}
相关资料
http://interview.wzcu.com/Golang/goroutine.html
https://go.cyub.vip/concurrency/channel/
https://blog.csdn.net/weixin_43870646/article/details/86575142