我很難搞清楚如何正確使用sync.Cond
。從我所知道的情況來看,在鎖定Locker和調用條件的Wait方法之間存在競爭條件。此示例將在主夠程的兩條線之間的人爲延遲,以模擬比賽條件:如何正確使用sync.Cond?
package main
import (
"sync"
"time"
)
func main() {
m := sync.Mutex{}
c := sync.NewCond(&m)
go func() {
time.Sleep(1 * time.Second)
c.Broadcast()
}()
m.Lock()
time.Sleep(2 * time.Second)
c.Wait()
}
這會導致立即恐慌:
fatal error: all goroutines are asleep - deadlock! goroutine 1 [semacquire]: sync.runtime_Syncsemacquire(0x10330208, 0x1) /usr/local/go/src/runtime/sema.go:241 +0x2e0 sync.(*Cond).Wait(0x10330200, 0x0) /usr/local/go/src/sync/cond.go:63 +0xe0 main.main() /tmp/sandbox301865429/main.go:17 +0x1a0
什麼我做錯了嗎?我如何避免這種明顯的競爭條件?有沒有更好的同步構造,我應該使用?
編輯:我知道我應該有更好的解釋,我想在這裏解決的問題。我有一個長時間運行的goroutine,它可以下載一個大文件和許多其他需要訪問HTTP標頭的goroutine。這個問題比聽起來更難。
我不能使用頻道,因爲只有一個goroutine會收到該值。還有一些其他的goroutines會試圖在標題已經可用之後很長時間檢索它。
下載程序goroutine可以簡單地將HTTP頭存儲在變量中,並使用互斥鎖來保護對它們的訪問。但是,這並不能爲其他goroutines「等待」它們變得可用提供一種方法。
我原本以爲sync.Mutex
和sync.Cond
一起可以實現這個目標,但看起來這是不可能的。
如果有什麼是不可能啓動夠程前鎖定互斥?例如,可能有其他的goroutine調用Wait()。 –
比可能的情況是,當調用廣播時,不會通知其他goroutine。這也很好 - 但我們都沒有提到 - 通常情況與某些國家有關。等待意味着 - 當系統處於這種狀態時,我無法繼續等待。廣播的意思是 - 狀態改變了,每個等待的人都應該檢查他是否可以繼續。請更準確地描述兩個例程中計算的內容,以及爲什麼他們必須相互交流。 – lofcek
對不起,我應該在原始問題中詳細介紹一下。我添加了一個編輯,描述了我正在嘗試做的事情。 –