Ответ
Да, может, и это одна из ключевых особенностей Go, обеспечивающая высокую производительность для конкурентных задач.
Горутины (goroutines) — это легковесные потоки, управляемые средой выполнения Go (Go runtime), а не напрямую операционной системой. Они работают поверх небольшого пула системных потоков ОС.
Go использует модель планирования M:N, где M горутин выполняются на N потоках ОС (где N обычно равно количеству доступных ядер CPU).
Ключевые преимущества горутин перед потоками ОС:
- Низкое потребление памяти: Стек горутины начинается всего с ~2 КБ, в то время как стек системного потока занимает ~1 МБ.
- Быстрое переключение: Переключение между горутинами происходит в пространстве пользователя (user-space) и управляется планировщиком Go, что намного быстрее, чем переключение системных потоков, требующее вызова ядра ОС.
- Масштабируемость: Благодаря этим особенностям, приложение на Go может легко поддерживать сотни тысяч и даже миллионы одновременно работающих горутин.
Пример:
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
fmt.Printf("Количество ядер CPU: %dn", runtime.NumCPU())
// Запускаем 10 000 горутин
for i := 0; i < 10000; i++ {
go func(n int) {
// Каждая горутина выполняет небольшую работу
time.Sleep(time.Millisecond * 10)
}(i)
}
fmt.Printf("Текущее количество горутин: %dn", runtime.NumGoroutine())
// Даем время на выполнение части горутин
time.Sleep(time.Second)
fmt.Printf("Количество горутин после ожидания: %dn", runtime.NumGoroutine())
}