0
点赞
收藏
分享

微信扫一扫

微信收款码费率0.38太坑了

全栈顾问 2023-09-25 阅读 46

sync.WaitGroup 是 Go 语言标准库中的一个并发原语,用于等待一组并发操作的完成。它提供了一种简单的方式来跟踪一组 goroutine 的执行状态,并在所有 goroutine 完成后恢复执行。

下面是关于 sync.WaitGroup 的实现细节的详细解释:

  • 创建 WaitGroup
    可以通过创建 sync.WaitGroup 类型的变量来创建 WaitGroup:
var wg sync.WaitGroup
  • 添加任务
    使用 Add 方法将要等待的任务数量加一。每个任务都应该在启动之前调用 Add,以确保 WaitGroup 知道要等待的任务数量。
wg.Add(1) // 添加一个任务
  • 完成任务
    在每个任务完成时,应调用 Done 方法来通知 WaitGroup 该任务已完成。
wg.Done() // 完成一个任务

等待任务完成:
使用 Wait 方法来阻塞当前 goroutine,直到所有的任务都完成。

wg.Wait() // 等待所有任务完成

如果在调用 Wait 之前已经调用了 Add,那么 Wait 将会阻塞并等待所有任务完成。一旦所有任务完成,Wait 将返回,允许当前 goroutine 继续执行。

注意,Wait 方法可以在任何地方调用,但是需要确保在所有添加任务的地方都已经调用了 Add 方法,以避免出现死锁。
需要注意的是,WaitGroup 是通过内部计数器来实现的。每次调用 Add 方法增加计数器的值,每次调用 Done 方法减少计数器的值。当计数器的值为零时,等待的任务被认为已经完成。

下面是一个简单的示例,演示如何使用 WaitGroup:

package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	var wg sync.WaitGroup

	wg.Add(2) // 添加两个任务

	go func() {
		defer wg.Done() // 标记任务完成
		time.Sleep(1 * time.Second)
		fmt.Println("Task 1 completed")
	}()

	go func() {
		defer wg.Done() // 标记任务完成
		time.Sleep(2 * time.Second)
		fmt.Println("Task 2 completed")
	}()

	wg.Wait() // 等待所有任务完成
	fmt.Println("All tasks completed")
}

在上面的示例中,我们创建了一个 WaitGroup,并添加了两个任务。每个任务使用匿名函数表示,其中包含了任务的具体逻辑。在每个任务的最后,我们使用 defer wg.Done() 来标记任务的完成。最后,我们调用 wg.Wait() 来等待所有的任务完成,并在所有任务完成后打印 “All tasks completed”。

通过使用 WaitGroup,我们可以轻松地跟踪一组并发操作的完成状态,以便在需要时等待它们完成。这对于需要等待多个 goroutine 完成的并发任务非常有用,它包含一个计数器和两个方法:Add和Done。

Add方法用于增加计数器的值,表示有多少个goroutine需要等待。Done方法用于减少计数器的值,表示一个goroutine已经完成了它的工作。当计数器的值变为0时,Wait方法将返回,表示所有的goroutine都已经完成了它们的工作。

type WaitGroup struct {
    counter int32
    wait    chan struct{}
    lock    sync.Mutex
}

func (wg *WaitGroup) Add(delta int) {
    wg.lock.Lock()
    defer wg.lock.Unlock()
    wg.counter += int32(delta)
}

func (wg *WaitGroup) Done() {
    wg.Add(-1)
}

func (wg *WaitGroup) Wait() {
    wg.lock.Lock()
    if wg.counter == 0 {
        wg.lock.Unlock()
        return
    }
    wg.wait = make(chan struct{})
    wg.lock.Unlock()
    <-wg.wait
}

func (wg *WaitGroup) DoneAndWait() {
    wg.Done()
    wg.Wait()
}

在这个实现中,WaitGroup包含一个计数器和一个等待通道。Add方法使用互斥锁来保护计数器的并发访问。Done方法简单地调用Add方法并将delta设置为-1。Wait方法首先使用互斥锁来检查计数器的值是否为0。如果计数器的值为0,则立即返回。否则,它创建一个新的等待通道,并将其存储在WaitGroup中。最后,它释放互斥锁并等待等待通道上的信号。

举报

相关推荐

0 条评论