Ответ
В основе реализации каналов в Go лежат два основных механизма синхронизации из стандартной библиотеки и среды выполнения:
- Мьютекс (
sync.Mutex
): Для защиты от гонок данных при доступе к внутренним полям канала. - Очереди ожидания и семафоры: Для блокировки и пробуждения горутин.
Внутренняя структура канала (в исходном коде runtime/chan.go
она называется hchan
) содержит следующие ключевые поля:
// Упрощенная структура канала
type hchan struct {
qcount uint // текущее количество элементов в буфере
dataqsiz uint // размер буфера
buf unsafe.Pointer // указатель на циклический буфер
sendx uint // индекс для отправки в буфер
recvx uint // индекс для получения из буфера
recvq waitq // очередь горутин, ожидающих получения (sudog)
sendq waitq // очередь горутин, ожидающих отправки (sudog)
lock mutex // мьютекс для защиты всех полей выше
}
Как это работает:
Защита данных: Любая операция с каналом (отправка или получение) начинается с захвата
lock
(мьютекса). Это гарантирует, что только одна горутина в один момент времени может изменять состояние канала (его буфер, счетчики, очереди).Блокировка горутины:
- Если горутина пытается отправить данные в полный (или небуферизованный) канал, она добавляется в очередь ожидания
sendq
и переходит в состояние сна. - Если горутина пытается прочитать данные из пустого канала, она добавляется в очередь
recvq
и также засыпает.
- Если горутина пытается отправить данные в полный (или небуферизованный) канал, она добавляется в очередь ожидания
Пробуждение горутины:
- Когда другая горутина считывает данные из канала, она проверяет очередь
sendq
. Если там есть ожидающая горутина, она "пробуждается" и получает возможность завершить свою отправку. - Аналогично, при отправке данных в канал проверяется очередь
recvq
для пробуждения горутины, ожидающей на чтение.
- Когда другая горутина считывает данные из канала, она проверяет очередь
Таким образом, канал — это не просто буфер данных, а сложная структура данных, которая инкапсулирует в себе всю логику для безопасной и эффективной синхронизации горутин.