Sobes.tech
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 GOMAXPROCS orqali 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:

  1. Yangi goroutine yaratiladi va mavjud P ning lokal navbatiga joylashtiriladi.
  2. P bilan bog'langan M, lokal navbatdan goroutine oladi va uni bajaradi.
  3. Agar lokal navbat bo'sh bo'lsa, M boshqa P dan goroutine'larni o'g'irlashga harakat qiladi.
  4. 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.
  5. Agar goroutine kanal yoki mutexda bloklansa, u kutish navbatiga qo'yiladi va rejalashtiruvchi boshqa goroutine ni tanlaydi, shuningdek, ayni M da bajariladi.
  6. 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.