协程
# 什么是协程
协程是一种比线程更加轻量级的存在,它是由用户态的线程调度器来调度的,而不是由操作系统内核来调度。
在应用层面可以理解为就是 Java 中的线程,但是协程的实现方式和 Java 中的线程有很大的不同。
相较于Java的线程解决了什么问题
- 线程的创建和销毁需要操作系统内核的参与,而协程的创建和销毁只需要用户态的线程调度器的参与,因此协程的创建和销毁比线程更加轻量级。
# 协程的创建
协程的创建需要使用 go
关键字,例如:
package main
import (
"fmt"
"time"
)
func main() {
// 匿名函数创建协程
go func() {
fmt.Println("hello")
}()
// 函数创建协程
go hello()
time.Sleep(time.Second)
}
func hello() {
fmt.Println("hello")
}
# 协程的退出
协程的退出有两种方式:
- 协程中的函数执行完毕,协程自动退出
- 协程中的函数使用
return
关键字退出
# 协程的通信
协程之间的通信可以使用 channel
来实现, channel
是一种特殊的类型,它可以让协程之间进行通信。
# 无缓冲的 channel
package main
import "fmt"
func main() {
// 定义一个channel
c := make(chan int)
go func() {
defer fmt.Println("子协程结束")
fmt.Println("子协程开始")
c <- 666
}()
num := <- c // 从channel中取出数据
fmt.Println("num = ", num)
fmt.Println("main协程结束")
}
- 在第 1 步,两个 goroutine 都到达通道,但哪个都没有开始执行发送或者接收。
- 在第 2 步,左侧的 goroutine 将它的手伸进了通道,这模拟了向通道发送数据的行为。这时,这个 goroutine 会在通道中被锁住,直到交换完成。
- 在第 3 步,右侧的 goroutine 将它的手放入通道,这模拟了从通道里接收数据。这个 goroutine 一样也会在通道中被锁住,直到交换完成。
- 在第 4 步和第 5 步,进行交换,并最终,在第 6 步,两个 goroutine 都将它们的手从通道里拿出来,这模拟了被锁住的 goroutine 得到释放。两个 goroutine 现在都可以去做其他事情了。
# 有缓冲的 channel
上次更新: 2024/03/11, 22:37:05