本教材由知了传课辛苦制作而成,仅供学习使用,请勿用于商业用途!如进行转载请务必注明出处!谢谢!

go中使用并发

goroutine必定对应一个函数,

多个goroutine可以执行相同的函数

Go程序就会为main()函数创建一个默认的goroutine。

一、goroutine的使用

package main

import (
"fmt"
)

func Hello() {
fmt.Println("hello执行完成")
}
func main() {
go Hello()
fmt.Println("main执行完成") // 会消耗时间,所以协程会执行
}


--》
main执行完成
hello执行完成

先执行主协程,其他的协程创建需要时间,所以是先执行main,再执行Hello,那个空闲执行那个

主协程终止,其他协程也会终止

二、多个goroutine

package main

import (
"fmt"
)

func Hello1() {
fmt.Println("Hello1执行完成")
}

func Hi1() {
fmt.Println("Hi1执行完成")
}

func main() {
go Hi1()
go Hello1()
fmt.Println("main执行完成")
time.Sleep(time.Second * 5)
}

goroutine的调度是随机的,除了主协程,其他的协程随机调度

三、sync.WaitGroup的使用

我们不知道协程执行完成需要多少时间,所以使用time.Sleep()不知道给多少时间合适

两种方法:

  • sync.WaitGroup

  • chan:看chan章节

1.介绍

sync:synchronization同步这个词的缩写,所以也会叫做同步包

WaitGroup:同步等待组。内部有一个计数器,从0开始,不能为负数

2.使用

  • Add(delta int):设置计数器
  • Done():会把计数器-1
  • Wait():会阻塞代码的运行,直到计数器地值减为0,为0终止

示例代码:

package main

import (
"fmt"
"sync"
)

var wg = sync.WaitGroup{}

func Hi() {
fmt.Println("Hi执行完成")
wg .Done()
}

func main() {
for i := 0; i < 10; i++ {
wg.Add(1) //每创建一个goroutine,就把任务队列中任务的数量+1
go Hi2() // 这里如果创建两个goroutine呢,签名的Add()里面是2?

}
wg.Wait() //.Wait()这里会发生阻塞,直到队列中所有的任务结束就会解除阻塞
fmt.Println("主协程结束")
}

四、Goroutine池

1.前言

  • goroutine虽然很小,但是当无休止的开辟Goroutine会出现高频率的调度Groutine,会浪费很多资源的同时占用很大的内存,怎么办呢?设计一个goroutine池,限制协程上限,重用协程,不要每次都去创建一个新的协程。

2.作用

  • 大量的goroutine会占用大量的内存,Goroutine池可以减轻内存负担
  • 性能消耗:重复的创建与销毁goroutine,大量的goroutine调度等会占用资源,Goroutine池可以减轻资源消耗
  • 减少goroutine创建时间,提高效率
  • 管理协程,控制并发量,定期回收等

3.实现思路

  • 启动服务的时候初始化一个Goroutine Pool,这个协程池维护了任务的管道和worker。

  • 外部将请求投递到Goroutine Pool,Goroutine Pool的操作是:判断当前运行的worker是否已经超过Pool的容量,如果超过就将请求放到任务管道中直到运行的worker将管道中的任务执行;如果没有超过就新开一个worker处理。

4.代码实现

  • 任务
  • 创建任务
  • 执行任务
  • 协程池
  • 创建协程池
  • 任务投递及任务执行(读写chan)
  • 协程池开启

1337人已阅读,今天你学习了吗?

添加新回复