1、goroutine
Golang 在语言层面对并发编程提供支持,一种类似协程,称作 goroutine 的机制。
只需在函数调用语句前添加 go 关键字,就可创建并发执行单元。开发人员无需了解任何执行细节,调度器会自动将其安排到合适的系统线程上执行。goroutine 是一种非常轻量级的实现,可在单个进程里执行成千上万的并发任务。
事实上,入口函数 main 就以 goroutine 运行。另有与之配套的 channel 类型,用以实现 “以通讯来共享内存” 的 CSP 模式。
2、channel
hannel 是 CSP 模式的具体实现,用于多个 goroutine 通讯。
其内部实现了同步,确保并发安全。多个goroutine同时访问,不需要加锁。
由于管道容量是5,开启go写入10个数据,再写入5个数据,会阻塞,然而read每秒会读取一个,然后在会写入一个数据。
3、WaitGroup
WaitGroup在go语言中,用于线程同步,单从字面意思理解,wait等待的意思,group组、团队的意思,WaitGroup就是指等待一组,等待一个系列执行完成后才会继续向下执行。
先说说WaitGroup的用途:它能够一直等到所有的goroutine执行完成,并且阻塞主线程的执行,直到所有的goroutine执行完成。
WaitGroup总共有三个方法:Add(delta int),Done(),Wait()。简单的说一下这三个方法的作用。
Add:添加或者减少等待goroutine的数量
Done:相当于Add(-1)
Wait:执行阻塞,直到所有的WaitGroup数量变成0
代码实现
package main
import (
"fmt"
"sync"
"time"
)
func write(ch chan int, wait *sync.WaitGroup) {
defer wait.Done()
for i := 0; i < 10; i++ {
ch <- i
fmt.Println("put data:", i)
}
close(ch)
}
func read(ch chan int, wait *sync.WaitGroup) {
defer wait.Done()
for {
// var b int
b, ok := <-ch
fmt.Println(b)
if !ok {
// os.Exit(1)
break
}
time.Sleep(time.Second)
}
}
func main() {
wg := sync.WaitGroup{}
wg.Add(2)
intChan := make(chan int, 5)
go write(intChan, &wg)
go read(intChan, &wg)
wg.Wait()
// time.Sleep(20 * time.Second)
}
结果
put data: 0
put data: 1
put data: 2
put data: 3
put data: 4
put data: 5
0
1
put data: 6
2
put data: 7
3
put data: 8
4
put data: 9
5
6
7
8
9
0