РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
823 of 1593 menu

Буферизованный канал

Буферизованный канал - это канал с буфером, который позволяет отправлять данные без блокировки, пока буфер не заполнится, и принимать данные без блокировки, пока буфер не опустеет. При создании канала указывается его вместимость. Когда горутина отправляет значение в буферизованный канал, операция не блокируется, если в буфере есть свободное место. Аналогично, получение данных не блокируется, если буфер не пуст.

Синтаксис

make(chan Type, capacity)

Первый параметр определяет тип данных, которые будут передаваться через канал, второй - размер буфера. Для отправки данных используется оператор <-, а для приема - оператор <-.

Пример

Создадим буферизованный канал с вместимостью 2 и отправим в него два значения без блокировки:

package main import "fmt" func main() { ch := make(chan string, 2) ch <- "first" ch <- "second" fmt.Println(<-ch) fmt.Println(<-ch) }

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

"first" "second"

Отправка двух значений не блокируется, так как буфер вмещает оба. После этого мы получаем их в порядке очереди.

Пример

Если буфер переполнен, отправка блокируется до тех пор, пока не появится свободное место. Аналогично, если буфер пуст, получение блокируется до появления данных. Рассмотрим пример с горутинами:

package main import ( "fmt" "time" ) func main() { ch := make(chan int, 2) go func() { time.Sleep(2 * time.Second) ch <- 42 fmt.Println("Sent 42") }() fmt.Println("Waiting for value...") value := <-ch fmt.Println("Received:", value) }

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

"Waiting for value..." "Sent 42" "Received: 42"

Горутина отправляет значение после задержки. Основная горутина блокируется при попытке получения данных, так как буфер пуст, и ожидает, пока значение не будет отправлено.

Пример

Использование буферизованного канала для ограничения количества одновременно выполняемых горутин. Это полезно для управления параллелизмом:

package main import ( "fmt" "sync" ) func main() { const maxWorkers = 2 sem := make(chan struct{}, maxWorkers) var wg sync.WaitGroup for i := 1; i <= 5; i++ { wg.Add(1) go func(id int) { defer wg.Done() sem <- struct{}{} defer func() { <-sem }() fmt.Printf("Worker %d started\n", id) fmt.Printf("Worker %d finished\n", id) }(i) } wg.Wait() }

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

"Worker 3 started" "Worker 3 finished" "Worker 5 started" "Worker 5 finished" "Worker 4 started" "Worker 4 finished" "Worker 1 started" "Worker 1 finished" "Worker 2 started" "Worker 2 finished"

В этом примере канал sem используется как семафор. Он позволяет запускать не более двух горутин одновременно. Каждая горутина отправляет пустую структуру в канал перед началом работы и получает ее после завершения, освобождая место для следующей.

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

  • канал chan,
    который описывает базовый синтаксис и принцип работы каналов
  • небуферизованный канал unbuffered-chan,
    который не имеет буфера и требует одновременной готовности отправителя и получателя
  • горутину goroutine,
    которая используется для параллельного выполнения кода с каналами
  • оператор выбора select,
    который позволяет ожидать операции с несколькими каналами
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить