从并发到并行解析Go语言中的sync.WaitGroup
是一篇介绍Go语言中并发编程工具的文章。在该篇文章中,我们会深入了解到什么是并发和并行,以及如何使用sync.WaitGroup
来协调并发和并行工作。
并发和并行的定义
并发是指同时执行多个代码段,但并不保证这些代码段的执行顺序。一个被操作系统调度器管理的Go程序就是一个并发程序。
并行是指同时执行多个代码段,并且这些代码段的执行是有序的。Go语言中提供了goroutine
和channel
来实现并行。
sync.WaitGroup
的简介
sync.WaitGroup
是Go语言标准库中用来协调goroutine的并发工具。它通常用在等待一组goroutine执行完毕后,在主goroutine中继续执行程序。sync.WaitGroup
包含以下三个方法:
func (wg *WaitGroup) Add(delta int)
:添加要等待的goroutine数量。func (wg *WaitGroup) Done()
:表示一个goroutine执行完毕。func (wg *WaitGroup) Wait()
:等待所有goroutine执行完毕。
使用sync.WaitGroup
的例子
下面的例子演示了如何使用sync.WaitGroup
等待goroutine执行完毕:
package main
import (
"fmt"
"sync"
"time"
)
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Printf("Worker %d is starting\n", id)
time.Sleep(time.Second)
fmt.Printf("Worker %d is done\n", id)
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1)
go worker(i, &wg)
}
wg.Wait()
fmt.Println("All workers are done")
}
在这个例子中,main()
函数启动了5个goroutine,并通过调用wg.Add(1)
来告诉WaitGroup
有多少个goroutine需要等待。每个goroutine执行完毕时,调用wg.Done()
告诉WaitGroup
已经完成一个goroutine。最后,Wait()
方法会一直等待全部goroutine执行完毕才会返回。
下面的例子演示了如何使用sync.WaitGroup
和channel来并行计算斐波那契数列:
package main
import (
"fmt"
"sync"
)
func fib(n int, c chan int, wg *sync.WaitGroup) {
defer wg.Done()
if n < 2 {
c <- n
return
}
var wg2 sync.WaitGroup
wg2.Add(2)
go fib(n-1, c, &wg2)
go fib(n-2, c, &wg2)
wg2.Wait()
a := <-c
b := <-c
c <- a + b
}
func main() {
c := make(chan int)
var wg sync.WaitGroup
wg.Add(1)
go fib(10, c, &wg)
wg.Wait()
fmt.Println(<-c)
}
在这个例子中,每一个fib
函数用来计算斐波那契序列。fib
函数首先判断是否满足递归终止条件,如果满足,则将n的值放入通道c
中。否则,会启动两个goroutine,分别计算n-1
和n-2
的斐波那契序列,并使用sync.WaitGroup
来等待它们完成。当两个goroutine完成计算并将结果放入通道中后,将这两个数相加并将结果放入通道中。在main
函数中,我们启动了一个计算斐波那契序列的goroutine,并通过Wait()
方法等待计算完成,然后从通道中读出结果并打印。
以上这两个例子分别展示了如何使用sync.WaitGroup
来简化并发和并行编程,省略了复杂的同步原语和锁机制。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:从并发到并行解析Go语言中的sync.WaitGroup - Python技术站