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