并发
协程(goroutine)
是 Go语言中的轻量级线程实现,内核态,线程可以跑多个协程,栈KB级别
创建:
-
常规:
go 函数名(函数列表) -
使用匿名函数:
go func(参数列表){函数体}(调用参数列表)调用参数列表:启动 goroutine 时,需要向匿名函数传递的调用参数
注意: 使用 go 关键字创建 goroutine 时,被调用函数的返回值会被忽略
channel
channel是 goroutine之间的通信机制。它可以让一个 goroutine 通过它给另一个 goroutine发送值信息
特点
- 在任何时候,同时只能有一个 goroutine 访问通道进行发送和获取数据
- 遵循先入先出的规则,保证收发数据的顺序
声明: var 通道变量 chan 通道类型
创建: 通道实例 := make(chan 数据类型,[缓冲大小])
带缓冲区的通道允许发送端的数据发送和接收端的数据获取处于异步状态
发送数据: 通道变量 <- 值
如果接收方没有接收,发送操作则将会持续阻塞
接收数据:
-
阻塞接收:
data := <-ch执行该语句时将会阻塞,直到接收到数据并赋值给data变量接受任意数据,忽略接收的数据:
<-ch -
非阻塞接收:
data, ok := <-ch可能造成高的 CPU 占用 -
循环接收:
for data := range ch {}
关闭: close(通道名)
锁
Mutex
创建: 锁名 sync.Mutex
当一个goroutine获得了 Mutex后,其他 goroutine就只能等到这个goroutine 释放该 Mutex
RWMutex
创建: 锁名 sync.RWMutex
在读锁占用的情况下,会阻止写但不阻止读,也就是多个goroutine可同时获取读锁(调用 RLock() 方法),而写锁(调用Lock() 方法)会阻止任何其他goroutine(无论读和写)进来,整个锁相当于由该 goroutine 独占
WaitGroup
是内置的 sync 包解决任务编排的并发原语,要解决的就是并发-等待的问题
基本用法
Add(delta int):用来设置WaitGroup的计数值;Done():用来将WaitGroup的计数值减1,其实就是调用了Add(-1);Wait():调用这个方法的goroutine会一直阻塞,直到WaitGroup的计数值变为0