Middle+
Go'da goroutine rejalashtirish haqida gapiring.
sobes.tech AI
AIdan javob
Go'dagi goroutinlarni rejalashtirish M:N modelini ishlatadi, bu yerda M goroutine N operatsion tizim iplariga mos keladi. U goroutinlarni iplar orasida samarali tarzda o'tkazadi va to'xtash nuqtalari (preemption points) bilan to'liq multitaskingni amalga oshiradi.
GPM modelining asosiy komponentlari:
- G (Goroutine): Ishga tushiriladigan kod birligi, yengil ip, Go rejalashtiruvchisi tomonidan boshqariladi.
- P (Protsessor): Mantiqiy protsessor, lokal goroutine navbati va mutexlar va rejalashtiruvchi kabi resurslarni ifodalaydi. P ning standart soni protsessorning mantiqiy yadro soni bilan belgilanadi, ammo
GOMAXPROCSorqali o'zgartirilishi mumkin. - M (Mashina/IP): Operatsion tizim ipi, kodni bajaradi. M P bilan bog'langan va P ning lokal navbatidan yoki global navbatdan goroutine'larni bajaradi.
Ishlash prinsipi:
- Yangi goroutine yaratiladi va mavjud P ning lokal navbatiga joylashtiriladi.
- P bilan bog'langan M, lokal navbatdan goroutine oladi va uni bajaradi.
- Agar lokal navbat bo'sh bo'lsa, M boshqa P dan goroutine'larni o'g'irlashga harakat qiladi.
- Agar P bloklansa (masalan, tizim chaqiruvi paytida), unga bog'langan M ajraladi va boshqa M bu P bilan bog'lanadi. Bloklangan M qayta ishlatilishi mumkin, tizim chaqiruvi tugagach.
- Agar goroutine kanal yoki mutexda bloklansa, u kutish navbatiga qo'yiladi va rejalashtiruvchi boshqa goroutine ni tanlaydi, shuningdek, ayni M da bajariladi.
- Rejalashtiruvchi uzun vaqt ishlayotgan goroutine'larni chiqarib yuborish uchun davriy tekshiruvlarni amalga oshiradi, bu bilan boshqa goroutine'lar CPU vaqti oladi.
Preemption nuqtalari muayyan joylarda yuzaga keladi:
- Funksiya/method chaqiruvlari.
- Funksiya chaqiruvlarini o'z ichiga olgan sikllar.
- Xotira ajratish.
- Sinxronizatsiya primitive'lari (kanallar, mutexlar).
Rejalashtirish misoli:
package main
import (
"fmt"
"runtime"
"time"
)
func worker(id int) {
fmt.Printf("Goroutine %d ish boshladi\n", id)
time.Sleep(time.Second) // Ishni simulyatsiya qilish
fmt.Printf("Goroutine %d ishni tugatdi\n", id)
}
func main() {
runtime.GOMAXPROCS(2) // Mantiqiy protsessorlar sonini belgilash
for i := 1; i <= 5; i++ {
go worker(i) // Goroutine'lar yaratish
}
time.Sleep(3 * time.Second) // Goroutine'larning yakunlanishini kutish
fmt.Println("Asosiy goroutine tugadi")
}
Bu misolda, 5 goroutine 2 mantiqiy protsessor uchun rejalashtiriladi. Go rejalashtiruvchisi, bu goroutine'larni mavjud operatsion tizim iplariga taqsimlaydi, lokal va ehtimol, global navbatlar va "work stealing" mexanizmi yordamida.
Bu yondashuvning afzalliklari:
- Katta o'lchovlilik: Ko'p yadroli tizimlardan samarali foydalanish.
- Past xarajatlar: OS iplariga nisbatan yengil goroutine'lar.
- Foydalanish osonligi: Tilga integratsiyalashgan rejalashtirish, parallel dasturlashni yanada qulay qiladi.