← Назад ко всем вопросам

Что будет с горутиной, если попытаться записать значение в заполненный буфер

1️⃣ Как кратко ответить

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

2️⃣ Подробное объяснение темы

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

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

Рассмотрим пример кода, чтобы понять, как это работает:

package main
​
import (
	"fmt"
	"time"
)
​
func main() {
	// Создаем буферизированный канал с размером буфера 2
	ch := make(chan int, 2)
​
	// Записываем два значения в канал
	ch <- 1
	ch <- 2
​
	// Попытка записать третье значение в заполненный буфер
	go func() {
		fmt.Println("Попытка записать 3 в канал")
		ch <- 3
		fmt.Println("Запись 3 завершена")
	}()
​
	// Задержка перед чтением из канала
	time.Sleep(1 * time.Second)
​
	// Чтение значений из канала
	fmt.Println(<-ch)
	fmt.Println(<-ch)
	fmt.Println(<-ch)
}
  1. ch := make(chan int, 2): Создается буферизированный канал ch с размером буфера 2. Это значит, что в канал можно записать два значения, прежде чем он станет полным.

  2. ch <- 1 и ch <- 2: Два значения записываются в канал. После этого буфер канала заполнен.

  3. go func() { ... }(): Анонимная горутина пытается записать третье значение 3 в канал. Поскольку буфер канала уже заполнен, эта горутина блокируется и ждет, пока в буфере не освободится место.

  4. time.Sleep(1 * time.Second): Задержка в 1 секунду, чтобы показать, что горутина действительно блокируется.

  5. fmt.Println(<-ch): Чтение первого значения из канала. Это освобождает место в буфере, и заблокированная горутина может продолжить выполнение, записав значение 3 в канал.

  6. fmt.Println(<-ch) и fmt.Println(<-ch): Чтение оставшихся значений из канала.

Таким образом, блокировка горутины при попытке записи в заполненный буфер позволяет синхронизировать выполнение горутин и предотвращает потерю данных. Это важный аспект работы с каналами в Go, который помогает управлять параллелизмом и координировать взаимодействие между горутинами.

Тема: Конкурентность
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки