Go语言进阶3 | 青训营笔记

65 阅读2分钟

这是我参与「第五届青训营」笔记创作活动的第13天 WaitGroup是Go语言中一个用于同步多个goroutine的并发原语,它提供了一种简单的方式来等待一组goroutine全部执行完毕,再继续执行后续的代码。

WaitGroup主要包含3个方法:

  1. Add(n int):增加WaitGroup的计数器,n表示增加的计数器数量。
  2. Done():减少WaitGroup的计数器,通知WaitGroup已完成一项任务。
  3. Wait():阻塞直到WaitGroup的计数器变为0,即所有任务都已完成。

当使用WaitGroup时,需要注意以下几点:

  1. Add方法应该在启动goroutine之前调用,否则可能会漏掉一些goroutine。
  2. Done方法应该在goroutine的最后调用,否则可能会导致计数器没有减少。
  3. Wait方法应该在主函数的最后调用,否则可能会阻塞主函数的执行。
  4. 计数器初始值应该为0,否则可能会出现计数器一直为0的情况。
  5. WaitGroup对象不能复制,否则可能会导致计数器不正确。

在实际使用WaitGroup时,可以将它与其他并发原语一起使用,例如MutexChannel等。下面是一个稍微复杂一些的示例代码,展示了如何使用WaitGroupMutex来实现一个并发安全的计数器:

WaitGroup通常的使用场景是在主函数中启动多个goroutine,等待这些goroutine全部执行完毕后,再继续执行主函数的后续代码。这个过程通常会包括以下几个步骤:

  1. 在主函数中创建WaitGroup对象,并设置计数器为0。
  2. 在启动goroutine之前,通过Add方法增加WaitGroup的计数器。
  3. 在每个goroutine的最后,通过Done方法减少WaitGroup的计数器。
  4. 在主函数的最后,通过Wait方法阻塞等待所有goroutine执行完毕。

下面是一个简单的示例代码,展示了WaitGroup的基本用法:

package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup

	for i := 0; i < 5; i++ {
		wg.Add(1)

		go func(id int) {
			defer wg.Done()

			fmt.Printf("goroutine %d is done\n", id)
		}(i)
	}

	wg.Wait()

	fmt.Println("all goroutines are done")
}

在这个示例中,我们首先创建了一个WaitGroup对象,然后启动了5个goroutine。每个goroutine中打印一条消息,表示这个goroutine已经执行完毕。在每个goroutine的最后,我们调用了wg.Done()方法,表示这个goroutine已经完成了一个任务。在主函数的最后,我们调用了wg.Wait()方法,阻塞等待所有goroutine执行完毕。