Go并发:利用sync.WaitGroup实现协程同步
2017-05-25 09:28
337 查看
经常看到有人会问如何等待主协程中创建的协程执行完毕之后再结束主协程,例如如下代码:
执行以上代码很可能看不到输出,因为有可能这两个协程还没得到执行主协程已经结束了,而主协程结束时会结束所有其他协程。解决办法是可以在main函数结尾加上等待:
这并不是完美的解决方法,如果这两个协程中包含复杂的操作,可能很耗时间,就无法确定需要睡眠多久,当然可以用管道实现同步:
上面的解决方案是比较完美的方案,但是Go提供了更简单的方法——使用sync.WaitGroup。WaitGroup顾名思义,就是用来等待一组操作完成的。WaitGroup内部实现了一个计数器,用来记录未完成的操作个数,它提供了三个方法,Add()用来添加计数。Done()用来在操作结束时调用,使计数减一。Wait()用来等待所有的操作结束,即计数变为0,该函数会在计数不为0时等待,在计数为0时立即返回。
可见用sync.WaitGroup是最简单的方式。
package main import ( "fmt" ) func main() { go func() { fmt.Println("Goroutine 1") }() go func() { fmt.Println("Goroutine 2") }() }
执行以上代码很可能看不到输出,因为有可能这两个协程还没得到执行主协程已经结束了,而主协程结束时会结束所有其他协程。解决办法是可以在main函数结尾加上等待:
package main import ( "fmt" "time" ) func main() { go func() { fmt.Println("Goroutine 1") }() go func() { fmt.Println("Goroutine 2") }() time.Sleep(time.Second * 1) // 睡眠1秒,等待上面两个协程结束 }
这并不是完美的解决方法,如果这两个协程中包含复杂的操作,可能很耗时间,就无法确定需要睡眠多久,当然可以用管道实现同步:
package main import ( "fmt" ) func main() { ch := make(chan struct{}) count := 2 // count 表示活动的协程个数 go func() { fmt.Println("Goroutine 1") ch <- struct{}{} // 协程结束,发出信号 }() go func() { fmt.Println("Goroutine 2") ch <- struct{}{} // 协程结束,发出信号 }() for range ch { // 每次从ch中接收数据,表明一个活动的协程结束 count-- // 当所有活动的协程都结束时,关闭管道 if count == 0 { close(ch) } } }
上面的解决方案是比较完美的方案,但是Go提供了更简单的方法——使用sync.WaitGroup。WaitGroup顾名思义,就是用来等待一组操作完成的。WaitGroup内部实现了一个计数器,用来记录未完成的操作个数,它提供了三个方法,Add()用来添加计数。Done()用来在操作结束时调用,使计数减一。Wait()用来等待所有的操作结束,即计数变为0,该函数会在计数不为0时等待,在计数为0时立即返回。
package main import ( "fmt" "sync" ) func main() { var wg sync.WaitGroup wg.Add(2) // 因为有两个动作,所以增加2个计数 go func() { fmt.Println("Goroutine 1") wg.Done() // 操作完成,减少一个计数 }() go func() { fmt.Println("Goroutine 2") wg.Done() // 操作完成,减少一个计数 }() wg.Wait() // 等待,直到计数为0 }
可见用sync.WaitGroup是最简单的方式。
相关文章推荐
- Go 并发实现协程同步的多种解决方法
- GO 利用 sync 库实现 Barrier
- GO Contact Sync轻松实现OutLook与google同步
- Go并发:利用sync.Once延迟加载
- 利用触发器实现数据同步
- 利用触发器实现数据同步
- 利用数据库复制技术 实现数据同步更新
- 利用数据库复制技术实现数据同步更新
- 利用复制实现数据同步
- 利用数据库复制技术实现数据同步更新_SQL SERVER
- 利用实现数据同步功能, 已经完成测试,可以实现.
- 利用主动对象模型设计并发同步请求
- 孙鑫VC学习笔记:第十六讲 (二) 利用关键代码段实现线程间的同步
- 利用数据库复制技术 实现数据同步更新
- 利用数据库复制技术实现数据同步更新
- MSSQL数据同步利用数据库复制技术实现数据同步更新复制的概念
- 利用并发操作实现可伸缩性
- 利用oracle高级复制功能实现数据同步的问题
- 利用数据库复制技术 实现数据同步更新
- 利用数据库复制技术实现数据同步更新(SQL SERVER)