golang 协程等待

发布时间:2024-07-05 00:35:43

在Go语言中,协程是一种轻量级的并发编程模式,可以帮助开发者更好地利用多核处理器的计算能力。协程相比于线程的优势在于其更小的栈空间和高效的切换机制,使得开发者可以创建成千上万个协程而不会造成明显的负担。然而,在开发过程中,有时我们需要等待一个或多个协程完成后继续执行,这就需要使用协程的等待机制了。

1. 使用channel进行协程等待

在Go语言中,可以使用channel来实现协程的等待机制。通过在主协程中等待一个或多个子协程完成后再继续执行,可以实现协程的同步。

首先,我们可以通过创建一个无缓冲的channel来实现协程的同步等待。在主协程中,我们创建一个channel,并将其传递给子协程。子协程在完成任务后,通过往这个channel中发送一个值来通知主协程任务已经完成。主协程则在等待所有子协程完成后继续执行。下面是一个示例代码:

func main() { // 创建一个无缓冲的channel done := make(chan bool) // 子协程1 go func() { // 执行任务 time.Sleep(time.Second) // 发送一个值通知主协程任务完成 done <- true }() // 子协程2 go func() { // 执行任务 time.Sleep(time.Second * 2) // 发送一个值通知主协程任务完成 done <- true }() // 在主协程中等待所有子协程完成 <-done <-done // 所有子协程完成后继续执行 fmt.Println("All goroutines finished.") }

2. 使用sync.WaitGroup进行协程等待

除了使用channel外,Go语言还提供了一个更为直观的方式来等待多个协程的完成,即使用sync包中的WaitGroup结构。WaitGroup充当了一个计数器的角色,用于统计当前还未完成的协程数量。主协程可以通过调用Wait方法来等待所有协程完成后再继续执行。

示例代码如下:

func main() { var wg sync.WaitGroup // 启动两个子协程 wg.Add(2) go func() { // 执行任务 time.Sleep(time.Second) // 任务完成,计数减1 wg.Done() }() go func() { // 执行任务 time.Sleep(time.Second * 2) // 任务完成,计数减1 wg.Done() }() // 在主协程中等待所有子协程完成 wg.Wait() // 所有子协程完成后继续执行 fmt.Println("All goroutines finished.") }

3. 使用select语句进行协程等待

除了使用channel和WaitGroup外,Go语言还提供了一种更为灵活的协程等待方式,即使用select语句。通过select语句可以监听多个channel的消息,并在其中任意一个channel有消息到来时执行对应的操作。我们可以利用这一机制,将协程的任务完成情况转化为channel的接收操作,从而实现协程的等待。

下面是一个示例代码:

func main() { // 创建两个channel channel1 := make(chan bool) channel2 := make(chan bool) // 启动两个子协程 go func() { // 执行任务 time.Sleep(time.Second) // 发送一个值通知主协程任务完成 channel1 <- true }() go func() { // 执行任务 time.Sleep(time.Second * 2) // 发送一个值通知主协程任务完成 channel2 <- true }() // 在主协程中等待所有子协程完成 select { case <-channel1: fmt.Println("Goroutine 1 finished.") case <-channel2: fmt.Println("Goroutine 2 finished.") } <-channel1 <-channel2 // 所有子协程完成后继续执行 fmt.Println("All goroutines finished.") }

通过使用channel、WaitGroup和select语句等机制,我们可以灵活地控制协程的执行顺序和同步。这使得我们能够更好地利用Go语言的协程特性,开发出高效、并发的程序。

相关推荐