Golang中的同步工具Sync.Cond詳解
sync.Cond
sync.Cond是Golang標準庫提供的一個基于互斥鎖/讀寫鎖實現的條件變量類型,用于協調訪問共享資源的多個goroutine。當共享資源狀態發生變化時,可以通知等待條件變化而阻塞的goroutine。sync.Cond提供了一個創建方法和三個成員方法,如下:
- NewCond(l Locker) ,創建Cond對象,需要傳入一個鎖對象,互斥鎖或讀寫鎖;
- Wait(),阻塞當前goroutine,等待通知信號;
- Signal(),發送信號通知,喚醒一個等待的goroutine;
- Broadcast(),發送信號通知,喚醒多個等待的goroutine。
sync.Cond需要與一個互斥鎖或讀寫鎖一起使用,以確保不會同時操作共享資源。當處于鎖定狀態時,goroutine將阻塞在Wait()方法中,直到另一個goroutine通過Broadcast()、Signal()方法發出通知信號。
使用方法和示例
具體使用方法如下:
創建一個Mutex對象
var mutex = sync.Mutex{}
創建Cond對象,傳入Mutex
cond := sync.NewCond(&mutex)
等待通知信號,阻塞當前goroutine
cond.Wait()
發送通知信號,喚醒一個或多個等待的goroutine
cond.Signal() // 喚醒一個goroutine
// 或者 cond.Broadcast() 喚醒多個goroutine
看一個示例:
package main
import (
"log"
"sync"
"time"
)
func read(index int, c *sync.Cond) {
c.L.Lock()
c.Wait()
log.Println(index, "開始讀")
c.L.Unlock()
}
func write(c *sync.Cond) {
log.Println("開始寫")
time.Sleep(time.Second)
log.Println("喚醒其中一個goroutine")
c.Signal()
}
func main() {
cond := sync.NewCond(&sync.Mutex{})
for i := 1; i <= 5; i++ {
go func(index int) {
read(index, cond)
}(i)
}
write(cond)
time.Sleep(time.Second * 3)
}
輸出內容如下:
2023/05/19 22:01:34 開始寫
2023/05/19 22:01:35 喚醒其中一個goroutine
2023/05/19 22:01:35 2 開始讀
可以看出,Signal()方法只喚醒了一個goroutine,可以把第二十行更改為c.Broadcast(),運行看下效果,會發現所有goroutine都被喚醒了。
小結
sync.Cond通過基于底層機制制定通知等待列表,在goroutine等待通知時將它添加到等待通知的列表中,然后通過Signal()或Broadcast()方法發出通知信號來喚醒等待的goroutine,實現條件變量和goroutine的通信和同步。
使用sync.Cond可以使并發編程更加高效和靈活,避免了使用time.Sleep()或者空for循環的一些缺點。但是,使用條件變量也需要小心使用,必須避免死鎖和競態條件等問題。