Golang sync.Cond
Что такое sync.Cond?
sync.Cond в Go — это примитив синхронизации, который позволяет горутинам ожидать или сигнализировать о наступлении определенного события. Он полезен в ситуациях, когда одна или несколько горутин должны ждать, пока другая горутина не выполнит какое-то условие или не изменит состояние.
Основные методы sync.Cond:
Wait()— приостанавливает выполнение горутины до тех пор, пока не будет получен сигнал.Signal()— пробуждает одну горутину, ожидающую на этом условии.Broadcast()— пробуждает все горутины, ожидающие на этом условии.
Как работает sync.Cond?
1. Инициализация
sync.Cond создается с помощью функции sync.NewCond, которая принимает мьютекс (sync.Mutex или sync.RWMutex).
|
1 2 |
var mu sync.Mutex cond := sync.NewCond(&mu) |
2. Ожидание (Wait)
Горутина вызывает Wait(), чтобы приостановить свое выполнение. Внутри Wait() мьютекс автоматически разблокируется, чтобы другие горутины могли получить доступ к общим данным. Когда горутина получает сигнал (через Signal() или Broadcast()), она снова блокирует мьютекс и продолжает выполнение.
3. Сигнализация (Signal и Broadcast)
Signal()пробуждает одну горутину, ожидающую на этом условии.Broadcast()пробуждает все горутины, ожидающие на этом условии.
Пример использования sync.Cond:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
package main import ( "fmt" "sync" "time" ) func main() { var mu sync.Mutex cond := sync.NewCond(&mu) var ready bool // Горутина, которая ждет сигнала go func() { mu.Lock() for !ready { cond.Wait() // Ожидаем, пока ready не станет true } fmt.Println("Горутина: условие выполнено!") mu.Unlock() }() // Имитируем работу time.Sleep(2 * time.Second) // Меняем условие и отправляем сигнал mu.Lock() ready = true cond.Signal() // Пробуждаем одну горутину mu.Unlock() // Даем время для завершения time.Sleep(time.Second) } |
Когда использовать sync.Cond?
sync.Cond полезен в следующих сценариях:
- Ожидание изменения состояния: Например, когда одна горутина должна ждать, пока другая горутина не обновит общие данные.
- Координация между горутинами: Например, когда несколько горутин должны ждать, пока главная горутина не выполнит определенное действие.
Основные моменты:
- Мьютекс обязателен:
sync.Condвсегда работает в связке с мьютексом. Мьютекс защищает общие данные, которые проверяются в условии. - Проверка условия в цикле: После пробуждения горутины из
Wait(), условие следует проверять снова в цикле, чтобы избежать ложных пробуждений (spurious wakeups). Broadcast()vsSignal(): ИспользуйтеBroadcast(), если нужно пробудить все горутины, иSignal(), если достаточно пробудить одну.
Пример с Broadcast():
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
package main import ( "fmt" "sync" "time" ) func main() { var mu sync.Mutex cond := sync.NewCond(&mu) var ready bool // Несколько горутин, ожидающих сигнала for i := 0; i < 5; i++ { go func(id int) { mu.Lock() for !ready { cond.Wait() } fmt.Printf("Горутина %d: условие выполнено!\n", id) mu.Unlock() }(i) } // Имитируем работу time.Sleep(2 * time.Second) // Меняем условие и отправляем сигнал всем mu.Lock() ready = true cond.Broadcast() // Пробуждаем все горутины mu.Unlock() // Даем время для завершения time.Sleep(time.Second) } |
Преимущества sync.Cond:
- Позволяет эффективно синхронизировать горутины, избегая активного ожидания (busy waiting).
- Упрощает координацию между горутинами, особенно в сложных сценариях.
Альтернативы sync.Cond:
- Каналы: В Go часто используют каналы для синхронизации горутин. Однако
sync.Condможет быть более удобным в случаях, когда нужно ждать изменения состояния. sync.WaitGroup: Подходит для ожидания завершения группы горутин, но не для ожидания изменения состояния.
Итог:
sync.Cond — это мощный инструмент для синхронизации горутин в Go. Он особенно полезен, когда горутины должны ждать изменения состояния или события. Однако его использование требует аккуратности, чтобы избежать гонок и ложных пробуждений. Если вы работаете с общими данными и условиями, sync.Cond может стать отличным выбором! 😊
Recommended Posts
Golang map и Swiss Table
16.03.2025
