Go语言同步编程:别再让你的Goroutine睡大觉了!

Posted 柏链学习社

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go语言同步编程:别再让你的Goroutine睡大觉了!相关的知识,希望对你有一定的参考价值。

对Go语言有一些了解的朋友一定明白,Go语言最大的特性是并发,可以启动成百上千甚至上万的Goroutine,不过由于Goroutine的过多,我们也不得考虑多个Goroutine之间协调配合的问题,毕竟它们不可避免的要共同操作相同的共享数据,如果一味的放任不管,那我们的数据很难保证准确无误!

与多进程、多线程的原理是一样的,我们在使用并发的同时,也必须解决因为并发而带来的协调、同步问题。Go语言为我们提供了channel的同步方式,虽然可以帮我们解决大多数问题,但由的时候还是稍显不足。在这一点方面Go语言借鉴了多进程以及多线程的处理思路,使用一些相同的套路可以更优雅的控制多个Goroutine之间的同步问题。下面,我在这里为大家介绍Go语言几款同步套路,本篇我们主要介绍一下与计数有关的同步策略。

WaitGroup 计数等待法

WaitGroup(简称wg)是Go语言当中一个非常经典的设计,它类似于多进程编程中wait功能,让主控进程可以等待子进程退出。wg的设计也是类似目的,我们都知道在main-goroutine退出时,其余goroutine也将随之结束生命,因此我们很多时候必须控制main-goroutine不能先行退出,而很多人采用的手段可能是让main-goroutine睡一觉,或者来一个死循环!

这显然不够优雅,例如我们要实现一个案例:启动10个goroutine,让他们打印一些信息后,按照顺序退出,每隔1s退出1个

对于了解Goroutine,并且会用time.Sleep的你,很可能会写出如下的代码:

/* Author : yekai Company: Pdj Email : gaoye@tokenpai.com File : wg.go*/package main
import ( "fmt" "time")
func main() { for i := 0; i < 10; i++ { go func(num int) { time.Sleep(time.Second * time.Duration(num)) fmt.Printf("I am %d Goroutine\n", num) }(i) }
time.Sleep(time.Second * 11) //一定要比那10个货能睡才行}

当然这个代码的执行结果也是符合预期的,为了保证main-goroutine最后退出,我们必须让它更能睡才行。但是这样明显不是奔着解决目的去的,我们并发是为了更高效的使用CPU,而不是为了睡觉!这个小例子我们可以用wg完美的实现,想要掌握wg也非常简单,3个API就够了!


//增加计数func (wg *WaitGroup) Add(delta int)//减少计数func (wg *WaitGroup) Done()//阻塞等待计数变为0func (wg *WaitGroup) Wait()

wg的思想就是启动Goroutine时可以用Add增加一个计数,Gorouine结束时可以用Done减少一个计数,而负责监控的Goroutine只需阻塞在Wait上等待要监控的那些家伙们都退出就可以了,什么时候计数变为0了,Wait也就会解除阻塞!所以使用wg,可以帮上述代码再实现一遍:


/* Author : yekai Company: Pdj Email : gaoye@tokenpai.com File : wg.go*/package main
import ( "fmt" "sync" "time")
var w sync.WaitGroup
func main() { for i := 0; i < 10; i++ { w.Add(1) //添加一个要监控的Goroutine数量 go func(num int) { time.Sleep(time.Second * time.Duration(num)) fmt.Printf("I am %d Goroutine\n", num) w.Done() //释放一个 }(i) }
w.Wait() //阻塞等待}

通过这个例子,我们也知道了一个事情,使用wg要用到sync包,其实Go语言涉及到同步相关的方法基本都在此包中。本篇作为一个开始,后续我们会继续介绍sync包其他的同步方式,敬请期待。

以上是关于Go语言同步编程:别再让你的Goroutine睡大觉了!的主要内容,如果未能解决你的问题,请参考以下文章

Go语言并发编程总结

go语言:一个简单的goroutine同步(synchronize)

别再让投稿信耽误你发稿啦!(附cover letter模板)

使用Go语言实现高效的并发编程

使用Go语言实现高效的并发编程

使用Go语言实现高效的并发编程