Go WaitGroup及Cond底层实现原理
WaitGroup
WaitGroup是Golang提供的一个线程同步的工具,它可以使一个线程等待一组线程的完成操作。
实现原理
WaitGroup内部有一个计数器,初始值为0。每次调用Add方法,计数器就加1;每次调用Done方法,计数器就减1;每次调用Wait方法,它会阻塞等待计数器的值为0。
var wg sync.WaitGroup
func main() {
for i := 0; i < 10; i++ {
wg.Add(1) // 计数器加1
go func(wg *sync.WaitGroup) {
defer wg.Done() // 计数器减1
fmt.Println("Hello, World!")
}(&wg)
}
wg.Wait() // 等待计数器为0
}
示例
一个等待多个goroutine完成的例子:
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
wg.Add(2)
go func(wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println("Routine 1")
}(wg)
go func(wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println("Routine 2")
}(wg)
wg.Wait()
fmt.Println("All routines are done!")
}
Cond
Cond是条件变量,是Go语言中一个比较底层的同步原语。它的作用是在多个goroutine之间协调调度执行。
实现原理
Cond是结合Mutex(锁)来使用的。开发人员可以使用Cond来等待或者触发某个事件的发生。当一个goroutine等待一个事件发生时,它会阻塞自己并释放Mutex锁,供其他的goroutine使用。当事件发生时,其他的goroutine可以通知正在等待的goroutine,使得它重新开始执行。
type Cond struct {
noCopy noCopy
L Locker // 互斥锁
notify notifyList
checker copyChecker // 用来检查复制
}
Cond类型内部包含一个互斥锁,一个通知列表(notifyList)和一个复制检查器(copyChecker)。
示例
下面是一个生产者/消费者模型的示例:
package main
import (
"fmt"
"sync"
)
var buffer []int
var bufferLock sync.Mutex
var bufferCond = sync.NewCond(&bufferLock)
var done = make(chan bool)
func producer() {
for i := 0; i < 10; i++ {
bufferLock.Lock()
buffer = append(buffer, i)
fmt.Println("Producing...", i)
bufferLock.Unlock()
bufferCond.Signal() // 唤醒一个消费者
}
done <- true
}
func consumer(id int) {
for {
bufferLock.Lock()
for len(buffer) == 0 {
bufferCond.Wait() // 挂起等待直到收到生产者的信号
}
value := buffer[0]
buffer = buffer[1:]
fmt.Printf("Consumer %d consuming %d\n", id, value)
bufferLock.Unlock()
}
}
func main() {
for i := 0; i < 3; i++ {
go consumer(i)
}
go producer()
<-done
fmt.Println("Done!")
}
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Go WaitGroup及Cond底层实现原理 - Python技术站