go 怎么等待所有的协程完成_Go语言入门必知教程-协程

Golang中的并发性是指函数独立运行的能力。Goroutines就是能够并发运行的函数,也叫协程,它们是Golang提供作为并发处理操作的方法。

使用go语句创建协程goroutines

要将函数作为goroutine运行,以go语句为前缀调用函数。下面是示例代码块:

sum() // 正常的函数调用,该函数执行完返回后再执行下一条语句,这是同步调用

go sum() // 作为协程的函数调用,不等该函数执行完成直接执行下一条语句,这是异步调用

关键字go调用函数后立即返回,而函数作为协程在后台运行,程序的其余部分同时继续执行。每个Golang程序的main函数都是作为协程启动的,因此每个Golang程序至少运行一个goroutine。

创建协程

在每次调用函数responseSize之前添加go关键字。以下示例代码中有三个responseSize协程同时启动,对http.Get的三个调用也同时进行。程序不会等到一个响应返回后再发送下一个请求。因此,使用goroutines可以快速地打印三个响应的长度。

71b7cd95f9e7e33b703496c1cf55b6a4.png

结果:

C:Golang>go run main.go

Step1: https://www.baidu.com

Step1: https://www.sina.com.cn/

Step1: https://www.toutiao.com/

Step2: https://www.sina.com.cn/

Step3: https://www.sina.com.cn/

Step4: 116749

Step2: https://www.baidu.com

Step3: https://www.baidu.com

Step4: 79551

Step2: https://www.toutiao.com/

Step3: https://www.toutiao.com/

Step4: 203842

在main函数中添加了一个time.Sleep的方法,它可以防止main函数在协程结束之前退出。调用time.Sleep(10*time.Second)将使main协程睡眠10秒。

等待协程执行完成

sync包的中WaitGroup类型用来等待程序执行完所有在主函数中启动的协程。它维护一个记录协程数量的计数器,WaitGroup的Wait方法阻塞程序的执行,直到WaitGroup计数器为零,程序才继续往下执行。

调用WaitGroup的Add方法用于向WaitGroup添加计数器。

在协程里面使用defer语句调用WaitGroup的Done方法来减少WaitGroup计数器。

调用WaitGroup的Wait方法等待程序完成所有协程。

在主函数内部调用Wait方法,该方法阻止程序执行,直到WaitGroup计数器达到0的值,确保执行完所有协程。

e12aeb48b68ae181303add24db8cf733.png

结果:

C:Golang>go run main.go

Start Goroutines

Step1: https://www.toutiao.com/

Step1: https://www.baidu.com

Step1: https://www.sina.com.cn/

Step2: https://www.sina.com.cn/

Step3: https://www.sina.com.cn/

Step4: 116749

Step2: https://www.baidu.com

Step3: https://www.baidu.com

Step4: 79801

Step2: https://www.toutiao.com/

Step3: https://www.toutiao.com/

Step4: 203842

从协程里获取值

从协程里获取值的最便捷的方法是通道。通道是连接并发性协程的管道。将值从一个协程里发送到通道中,另一个协程或同步函数再从通道里接收这些值。

f1b0beedb9030b9ee36bb3c42e153bda.png

结果:

C:Golang>go run main.go

79655

运行和暂停协程的执行

使用管道可以运行和暂停协程的执行。管道就像是协程之间的协调者,用来进行这些操作。

796b2d80c676cbc185e7dc4f8e36b26a.png

结果:

1

2

3

4

Pause

Play

5

6

7

8

9

Stop

使用原子函数修复竞争条件

由于对共享资源的访问不同步,并试图同时对该资源进行读写,因此会出现竞争使用资源的情况。

原子函数提供同步访问整型和指针的低级锁定机制。原子函数通常用于修复竞争条件。

sync包中atomic子包的函数通过锁定对共享资源的访问来支持同步协程。

712ccc7daa42b08d9b873b8b6bf59ed9.png

atomic包中的AddInt32函数通过强制一次只有一个协程可以执行和完成加法操作来同步整型值的更新。当协程试图调用任何atomic包的函数时,它们会自动地同步访问被限定的变量。

结果:

C:Golang>go run -race main.go

Counter: 15

如果使用counter++代替atomic.AddInt32(&counter, 1),则结果如下:

C:Golang>go run -race main.go

==================

WARNING: DATA RACE

Read at 0x0000006072b0 by goroutine 7:

main.increment()

C:/Golang/main.go:31 +0x76

Previous write at 0x0000006072b0 by goroutine 8:

main.increment()

C:/Golang/main.go:31 +0x90

Goroutine 7 (running) created at:

main.main()

C:/Golang/main.go:18 +0x7e

Goroutine 8 (running) created at:

main.main()

C:/Golang/main.go:19 +0x96

==================

Counter: 15

Found 1 data race(s)

exit status 66

使用互斥锁Mutex定义关键代码

互斥锁用于创建关键代码,关键代码内访问资源,从而确保一次只能有一个协程执行该部分代码。

f428c5837ed01fb97f466781be7dd7a9.png

结果:

C:Golang>go run -race main.go

PHP stands for Hypertext Preprocessor.

PHP stands for Hypertext Preprocessor.

The Go Programming Language, also commonly referred to as Golang

The Go Programming Language, also commonly referred to as Golang

Counter: 4

由互斥锁的Lock()方法和Unlock()定义关键代码保护对计数器的更新。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值