我最近開始學習 golang,遇到了這個 sync.Cond 函式。我很難理解這是如何作業的。
考慮下面的代碼
var sharedRsc = make(map[string]interface{})
func main() {
var wg sync.WaitGroup
mu := sync.Mutex{}
c := sync.NewCond(&mu)
wg.Add(1)
go func() {
defer wg.Done()
c.L.Lock()
// for len(sharedRsc) == 0 {
c.Wait()
// }
c.L.Unlock()
fmt.Println(sharedRsc["rsc1"])
}()
// writes changes to sharedRsc
c.L.Lock()
sharedRsc["rsc1"] = "foo"
c.Signal()
c.L.Unlock()
wg.Wait()
}
執行此操作時會導致死鎖。我知道原因可能是 c.Signal 在 c.Wait 之前被呼叫。
但我不明白的是,當我們取消注釋 for 回圈時,它會起作用。那么 for 回圈是如何解決這種競爭條件的呢?即使在這里也有可能在 c.Wait 之前呼叫 c.Signal 對嗎?
uj5u.com熱心網友回復:
您將需要 for 回圈,因為如果 cond 在第二個協程等待之前發出信號,它將在 Wait() 處死鎖,因為在那之后沒有人會發出信號。
考慮以下執行流程:
- 調整
sharedRsc - c.信號()
- wg.Wait()
- c.等待()
uj5u.com熱心網友回復:
這是如何正確使用sync.Cond.
如果每次寫入和讀取都有一個 goroutine,那么您并不真正需要sync.Cond- 一個sync.Mutex就足以在它們之間進行通信。sync.Cond在多個讀者等待共享資源可用的情況下可能很有用。
var sharedRsc = make(map[string]interface{})
func main() {
var wg sync.WaitGroup
wg.Add(2)
m := sync.Mutex{}
c := sync.NewCond(&m)
go func() {
// this go routine wait for changes to the sharedRsc
c.L.Lock()
for len(sharedRsc) == 0 {
c.Wait()
}
fmt.Println(sharedRsc["rsc1"])
c.L.Unlock()
wg.Done()
}()
go func() {
// this go routine wait for changes to the sharedRsc
c.L.Lock()
for len(sharedRsc) == 0 {
c.Wait()
}
fmt.Println(sharedRsc["rsc2"])
c.L.Unlock()
wg.Done()
}()
// this one writes changes to sharedRsc
c.L.Lock()
sharedRsc["rsc1"] = "foo"
sharedRsc["rsc2"] = "bar"
c.Broadcast()
c.L.Unlock()
wg.Wait()
}
您可以在Go Playground中使用它。
如果情況允許,仍然推薦使用通道來傳遞資料。
注意:sync.WaitGroup這里僅用于等待 goroutine 完成執行。
為了更好地理解,請參閱官方檔案:https ://pkg.go.dev/sync
還可以看到類似的 SO:如何正確使用 sync.Cond?
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/414256.html
標籤:
上一篇:type'Future<List<ChartSeries<BarChartModel,String>>>'不是型別'List<C
