Ответ
Тред (поток выполнения) — это наименьшая единица выполнения кода, которой операционная система может управлять независимо. Каждый процесс имеет как минимум один тред.
Ключевые характеристики тредов (OS Threads):
- Разделяемые ресурсы: Треды одного процесса разделяют общее адресное пространство, файловые дескрипторы и другие ресурсы.
- Собственный контекст: Каждый тред имеет свой собственный стек вызовов, счетчик команд и набор регистров.
- Планирование ОС: Создание, переключение контекста и управление тредами осуществляется непосредственно ядром операционной системы. Это относительно дорогостоящая операция.
Связь с горутинами в Go
Горутины — это не треды операционной системы. Это легковесные, абстрактные потоки выполнения, управляемые планировщиком Go (Go Runtime Scheduler).
- Легковесность: Горутины имеют небольшой начальный размер стека (около 2 КБ), который может динамически расти. Создание сотен тысяч горутин — обычная практика, в то время как создание такого же количества тредов ОС привело бы к исчерпанию системных ресурсов.
- Модель M:N: Планировщик Go реализует модель M:N, где M горутин выполняются на N тредах операционной системы. Это позволяет эффективно использовать процессорное время, так как если одна горутина блокируется (например, на операции ввода-вывода), планировщик может переключить на выполнение другую горутину на том же треде ОС, не блокируя сам тред.
- Переключение контекста: Переключение между горутинами происходит в пространстве пользователя (user space) и выполняется планировщиком Go, что на порядки быстрее, чем переключение контекста тредов ОС.
Пример на Go:
package main
import (
"fmt"
"sync"
"time"
)
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Printf("Горутина %d начала работуn", id)
time.Sleep(time.Second)
fmt.Printf("Горутина %d завершила работуn", id)
}
func main() {
var wg sync.WaitGroup
// Запускаем 3 горутины, которые могут выполняться параллельно
for i := 1; i <= 3; i++ {
wg.Add(1)
go worker(i, &wg) // Запуск горутины, а не треда ОС
}
// Ожидаем завершения всех горутин
wg.Wait()
fmt.Println("Все горутины завершены.")
}
Итог: Горутины — это высокоуровневая и более эффективная концепция для конкурентного программирования в Go, которая абстрагирует разработчика от сложностей прямого управления тредами ОС.