cond
?通常指?sync.Cond
,它是標準庫?sync
?包中用于實現?條件變量?的同步原語。條件變量在多 goroutine 協作場景中非常有用,尤其在需要根據特定條件協調多個 goroutine 的執行順序時。
sync.Cond
?的核心作用
條件變量用于?等待某個條件滿足?或?通知其他等待者條件已滿足。常用于以下場景:
-
一個或多個 goroutine 需要等待某個條件成立才能繼續執行。
-
某個 goroutine 負責修改條件,并通知其他等待的 goroutine。
sync.Cond
?的組成
type Cond struct {L Locker // 關聯的鎖(通常是 sync.Mutex 或 sync.RWMutex)
}
主要方法:
-
Wait()
-
調用前必須持有鎖(
c.L.Lock()
)。 -
釋放鎖并掛起當前 goroutine,等待被喚醒。
-
被喚醒后重新獲取鎖,繼續執行。
-
-
Signal()
-
喚醒一個等待的 goroutine(隨機選擇一個)。
-
-
Broadcast()
-
喚醒所有等待的 goroutine。
-
基本使用模式
var (mu sync.Mutexcond = sync.NewCond(&mu)ready bool
)// 等待條件滿足的 goroutine
func waiter() {mu.Lock()defer mu.Unlock()for !ready { // 必須用循環檢查條件(防止虛假喚醒)cond.Wait()}// 執行條件滿足后的操作
}// 修改條件并通知的 goroutine
func setter() {mu.Lock()ready = truemu.Unlock()cond.Signal() // 或 cond.Broadcast()
}
經典示例:生產者-消費者
package mainimport ("fmt""sync""time"
)func main() {var mu sync.Mutexcond := sync.NewCond(&mu)queue := make([]int, 0)// 消費者go func() {for {mu.Lock()for len(queue) == 0 {cond.Wait() // 等待隊列非空}item := queue[0]queue = queue[1:]fmt.Println("Consumed:", item)mu.Unlock()}}()// 生產者for i := 1; i <= 5; i++ {time.Sleep(1 * time.Second)mu.Lock()queue = append(queue, i)fmt.Println("Produced:", i)cond.Signal() // 通知消費者mu.Unlock()}
}
關鍵注意事項
-
必須用循環檢查條件
Wait()
?返回后條件可能仍未滿足(如虛假喚醒),需循環檢查:for conditionNotMet {cond.Wait() }
-
調用?
Wait()
?前必須持有鎖
否則會導致競態條件。 -
Signal
?vs?Broadcast
-
Signal
:喚醒一個等待者(適用于單消費者)。 -
Broadcast
:喚醒所有等待者(適用于多消費者或條件變化影響所有等待者)。
-
何時使用?sync.Cond
?
-
需要?基于復雜條件協調多個 goroutine。
-
需要?同時喚醒多個等待者(如資源釋放時喚醒所有等待的 goroutine)。
對于簡單場景,優先考慮使用?channel(Go 的推薦并發模式):
// 用 channel 實現類似功能
ch := make(chan int)// 生產者
go func() {ch <- 1
}()// 消費者
go func() {item := <-ch
}()