在Go语言中,递归函数中设置互斥(Mutex)和使用sync.WaitGroup来同步多个goroutine是一种常见的需求。以下是如何实现这两种机制的基础概念和相关示例代码。
sync.Mutex
提供了基本的锁定机制。Add()
方法增加计数,每个启动的goroutine完成后调用 Done()
减少计数,主goroutine通过 Wait()
阻塞直到计数为零。以下是一个示例,展示了如何在递归函数中使用 sync.Mutex
和 sync.WaitGroup
:
package main
import (
"fmt"
"sync"
)
var (
mu sync.Mutex
wg sync.WaitGroup
counter int
)
func recursiveFunction(n int) {
defer wg.Done() // 每次递归调用结束时减少WaitGroup计数
if n <= 0 {
return
}
mu.Lock() // 加锁保护共享资源
counter++ // 修改共享资源
fmt.Println("Counter:", counter)
mu.Unlock() // 解锁
wg.Add(1) // 增加WaitGroup计数
go recursiveFunction(n - 1) // 启动新的goroutine进行递归调用
}
func main() {
wg.Add(1) // 初始调用时增加WaitGroup计数
go recursiveFunction(5) // 启动初始goroutine
wg.Wait() // 等待所有goroutine完成
fmt.Println("All goroutines finished.")
}
mu.Lock()
和 mu.Unlock()
确保对 counter
的访问是线程安全的。counter
前加锁,修改完成后解锁。main
函数中调用 wg.Add(1)
表示有一个任务开始。recursiveFunction
中,每次启动新的goroutine前调用 wg.Add(1)
增加计数。wg.Done()
减少计数。main
函数中的 wg.Wait()
阻塞,直到所有goroutine完成。Lock()
都有对应的 Unlock()
,可以使用 defer
来保证解锁操作一定会被执行。Add()
和 Done()
的调用次数不匹配,可能会导致 Wait()
永远阻塞或提前返回。通过上述方法,可以在递归函数中有效地使用互斥锁和WaitGroup来管理并发和同步。
领取专属 10元无门槛券
手把手带您无忧上云