用syc.WaitGroup来等待go协程执行完毕, 顺便看看协程并发数的控制方法

本文主要是介绍用syc.WaitGroup来等待go协程执行完毕, 顺便看看协程并发数的控制方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        看程序:

package mainimport ("fmt""time"
)func print(i int) {time.Sleep(1e9)fmt.Println(i)
}func main() {for i := 0; i < 10; i++ {go func(n int) {print(n)}(i)}
}

         结果没有任何输出,因为主协程很快退出了。

         等待一下,变为:

package mainimport ("fmt""time"
)func print(i int) {time.Sleep(1e9)fmt.Println(i)
}func main() {for i := 0; i < 10; i++ {go func(n int) {print(n)}(i)}for {}
}

         结果:

7
9
3
4
5
8
0
6
1
2

 

       这种等待太傻了, 改为:

package mainimport ("fmt""sync""time"
)func print(i int) {time.Sleep(1e9)fmt.Println(i)
}func main() {var wg sync.WaitGroupfor i := 0; i < 10; i++ {wg.Add(1)go func(n int) {defer wg.Add(-1)  // same: defer wg.Done()print(n)}(i)}wg.Wait() 
}

         结果:

8
1
5
0
9
4
7
2
6
3

       分析一下wg.Wait执行等待操作, 直到wg的计数变为0才返回。 在上面例子中,Add(1)了10次, 然后Add(-1)了10次,刚好。 我们把程序变一下:

package mainimport ("fmt""sync""time"
)func print(i int) {time.Sleep(1e9)fmt.Println(i)
}func main() {var wg sync.WaitGroupwg.Add(11)for i := 0; i < 10; i++ {go func(n int) {defer wg.Add(-1)  // same: defer wg.Done()print(n)}(i)}wg.Wait() 
}

        可以看到,计数达到11次,但只有10次的add(-1), 显然wg.Wait永远无法退出,提示:fatal error: all goroutines are asleep - deadlock!

        再看:

package mainimport ("fmt""sync""time"
)func print(i int) {time.Sleep(1e9)fmt.Println(i)
}func main() {var wg sync.WaitGroupwg.Add(5)for i := 0; i < 10; i++ {go func(n int) {defer wg.Add(-1)  // same: defer wg.Done()print(n)}(i)}wg.Wait() 
}

        结果出错,提示信息:

panic: sync: WaitGroup is reused before previous Wait has returned

panic: sync: negative WaitGroup counter

        看到没, negative counter了。

 

        最后,来看看协程并发数目的控制。 假设有102个离线任务需要并发执行,难道要开102个协程吗? 来看看怎么控制:

package mainimport ("fmt""sync""time"
)func print(i int) {time.Sleep(1e9)
}func main() {var wg sync.WaitGroupbegin := time.Now().Unix()j := 0for i := 0; i < 102; i++ {wg.Add(1)go func(n int) {defer wg.Add(-1) print(n)}(i)j++if j == 10 {wg.Wait()j = 0}}wg.Wait() end := time.Now().Unix()fmt.Println(end - begin)
}

         分析下结果, 不难得知, 结果为11. 运行了一下, OK. 

         另外,要注意,即使写连续写多个wg.Wait,也没有问题。

         不多说。

 

 

这篇关于用syc.WaitGroup来等待go协程执行完毕, 顺便看看协程并发数的控制方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/684045

相关文章

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Git中恢复已删除分支的几种方法

《Git中恢复已删除分支的几种方法》:本文主要介绍在Git中恢复已删除分支的几种方法,包括查找提交记录、恢复分支、推送恢复的分支等步骤,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录1. 恢复本地删除的分支场景方法2. 恢复远程删除的分支场景方法3. 恢复未推送的本地删除分支场景方法4. 恢复

Python将大量遥感数据的值缩放指定倍数的方法(推荐)

《Python将大量遥感数据的值缩放指定倍数的方法(推荐)》本文介绍基于Python中的gdal模块,批量读取大量多波段遥感影像文件,分别对各波段数据加以数值处理,并将所得处理后数据保存为新的遥感影像... 本文介绍基于python中的gdal模块,批量读取大量多波段遥感影像文件,分别对各波段数据加以数值处

Window Server2016加入AD域的方法步骤

《WindowServer2016加入AD域的方法步骤》:本文主要介绍WindowServer2016加入AD域的方法步骤,包括配置DNS、检测ping通、更改计算机域、输入账号密码、重启服务... 目录一、 准备条件二、配置ServerB加入ServerA的AD域(test.ly)三、查看加入AD域后的变

Window Server2016 AD域的创建的方法步骤

《WindowServer2016AD域的创建的方法步骤》本文主要介绍了WindowServer2016AD域的创建的方法步骤,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、准备条件二、在ServerA服务器中常见AD域管理器:三、创建AD域,域地址为“test.ly”

NFS实现多服务器文件的共享的方法步骤

《NFS实现多服务器文件的共享的方法步骤》NFS允许网络中的计算机之间共享资源,客户端可以透明地读写远端NFS服务器上的文件,本文就来介绍一下NFS实现多服务器文件的共享的方法步骤,感兴趣的可以了解一... 目录一、简介二、部署1、准备1、服务端和客户端:安装nfs-utils2、服务端:创建共享目录3、服

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

Go语言实现将中文转化为拼音功能

《Go语言实现将中文转化为拼音功能》这篇文章主要为大家详细介绍了Go语言中如何实现将中文转化为拼音功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 有这么一个需求:新用户入职 创建一系列账号比较麻烦,打算通过接口传入姓名进行初始化。想把姓名转化成拼音。因为有些账号即需要中文也需要英

Python中使用defaultdict和Counter的方法

《Python中使用defaultdict和Counter的方法》本文深入探讨了Python中的两个强大工具——defaultdict和Counter,并详细介绍了它们的工作原理、应用场景以及在实际编... 目录引言defaultdict的深入应用什么是defaultdictdefaultdict的工作原理

使用Python进行文件读写操作的基本方法

《使用Python进行文件读写操作的基本方法》今天的内容来介绍Python中进行文件读写操作的方法,这在学习Python时是必不可少的技术点,希望可以帮助到正在学习python的小伙伴,以下是Pyth... 目录一、文件读取:二、文件写入:三、文件追加:四、文件读写的二进制模式:五、使用 json 模块读写