Метод sync.Cond.Wait

Метод sync.Cond.Wait приостанавливает выполнение текущей горутины и освобождает блокировку мьютекса, связанного с условной переменной. После получения сигнала (через Signal или Broadcast) горутина пробуждается и снова захватывает блокировку. В первый параметр метод не принимает аргументов. Он должен вызываться только внутри критической секции, защищенной мьютексом условной переменной.

Синтаксис

goc.Wait()

Пример

Давайте рассмотрим базовый пример использования sync.Cond.Wait для ожидания выполнения условия:

gopackage main

import (
  "fmt"
  "sync"
)

func main() {
  var mu sync.Mutex
  cond := sync.NewCond(&mu)
  ready := false

  // Горутина, которая будет ожидать сигнала
  go func() {
    mu.Lock()
    for !ready {
      cond.Wait()
    }
    fmt.Println("Goroutine is ready")
    mu.Unlock()
  }()

  // Основная горутина, которая меняет условие и отправляет сигнал
  mu.Lock()
  ready = true
  cond.Signal()
  mu.Unlock()

  // Небольшая задержка, чтобы горутина успела выполниться
  var wg sync.WaitGroup
  wg.Add(1)
  go func() {
    defer wg.Done()
    // Ожидаем завершения работы горутины
  }()
  wg.Wait()
}

Результат выполнения кода:

go"Goroutine is ready"

Пример

Рассмотрим пример с несколькими ожидающими горутинами и использованием Broadcast:

gopackage main

import (
  "fmt"
  "sync"
)

func main() {
  var mu sync.Mutex
  cond := sync.NewCond(&mu)
  counter := 0

  // Три горутины, ожидающие сигнала
  for i := 0; i < 3; i++ {
    go func(id int) {
      mu.Lock()
      for counter < 5 {
        cond.Wait()
      }
      fmt.Printf("Goroutine %d: counter = %d\n", id, counter)
      mu.Unlock()
    }(i)
  }

  // Основная горутина изменяет состояние и отправляет широковещательный сигнал
  mu.Lock()
  counter = 10
  cond.Broadcast()
  mu.Unlock()

  // Задержка для завершения всех горутин
  var wg sync.WaitGroup
  wg.Add(1)
  go func() {
    defer wg.Done()
  }()
  wg.Wait()
}

Результат выполнения кода:

go"Goroutine 2: counter = 10"
"Goroutine 0: counter = 10"
"Goroutine 1: counter = 10"

Смотрите также

  • функцию sync.NewCond,
    которая создает новую условную переменную
  • метод sync.Cond.Signal,
    который пробуждает одну ожидающую горутину
  • метод sync.Cond.Broadcast,
    который пробуждает все ожидающие горутины
  • тип sync.Cond,
    который представляет условную переменную в Go