Sobes.tech
Middle+

Goда goroutine-дардын пландоосу жөнүндө айтып бериңиз.

sobes.tech AI

AIден жооп

Go тилиндеги горутиндердин планалоочуусу M:N моделин колдонуп, анда M горутиндери N операциялык тутумдун жиптерине картачыланат. Ал горутиндерди жиптердин арасында эффективдүү которуп, токтотуу пункттары (preemption points) менен үзгүлтүксүз көп тапшырмалуулукту ишке ашырат.

GPM моделинин негизги компоненттери:

  • G (Goroutine): Коддун аткарылуучу бирдигинин абстракциясы, жеңил агым, Go планалоочу тарабынан башкарылат.
  • P (Processor): Логикалык процессор, жергиликтүү кезек жана мунайтекстер жана планалоочу сыяктуу ресурстардын контекстин көрсөтөт. Pдин саны алдын ала белгиленген процессордун логикалык ядролорунун санына ылайык келет, бирок GOMAXPROCS аркылуу өзгөртүлүшү мүмкүн.
  • M (Machine/Thread): Операциялык тутумдун агымы, кодду аткарат. M P менен байланышкан жана жергиликтүү кезектеги же глобалдык кезектеги горутиндерди аткарат.

Ишке ашыруу принциби:

  1. Жаңы горутина түзүлүп, жеткиликтүү Pнин жергиликтүү кезегине коюлат.
  2. P менен байланышкан M жергиликтүү кезектен горутинаны алат жана аткарат.
  3. Эгер жергиликтүү кезек бош болсо, M башка Pлердөн горутиналарды уурдап алууга аракет кылат.
  4. Эгер P блоктосо (мисалы, системдик чакырууда), ага байланышкан M ажыратылып, башка M ошол P менен байланышат. Блоктогон M кайра колдонулушу мүмкүн, системдик чакыруудан кийин.
  5. Эгер горутина канал же мунайтексте блоктосо, ал күтүүлөр кезегине коюлат, жана планалоочу ошол Mде башка горутинаны аткарууга тандайт.
  6. Планалоочу узак убакыт иштеген горутиналарды алдын алуу үчүн мезгил-мезгили менен текшерүүлөрдү жүргүзөт, башка горутиналарга аткаруу убактысын берет.

Preemption points (үзгүлтүккө учурауучу пункттар):

  • Функция/метод чакыруулары:
  • Функция чакырууларын камтыган циклдер:
  • Эстутү бөлүштүрүү:
  • Синхрондоштуруу primitives (каналдар, мунайтекстер):

Мисал пландоо:

package main

import (
	"fmt"
	"runtime"
	"time"
)

func worker(id int) {
	fmt.Printf("Горутин %d ишти баштады\n", id)
	time.Sleep(time.Second) // ишти имитациялоо
	fmt.Printf("Горутин %d ишти аяктады\n", id)
}

func main() {
	runtime.GOMAXPROCS(2) // Логикалык процессорлордун санын белгилөө

	for i := 1; i <= 5; i++ {
		go worker(i) // Горутиндерди түзүү
	}

	time.Sleep(3 * time.Second) // Горутиндердин аякташын күтүү
	fmt.Println("Негизги горутин аяктады")
}

Бул мисалда 5 горутин 2 логикалык процессорго пландалган. Go планалоочуусу бул горутиндерди операциялык тутумдун жеткиликтүү агымдарына бөлүштүрөт, жергиликтүү жана мүмкүн болсо глобалдык кезектерди колдонуп, ошондой эле "уурдап алуу" механизмин колдонулат.

Бул ыкманын артыкчылыктары:

  • Масштабдуулук: көпядролук системдердин эффективдүү колдонулушу.
  • Төмөн чыгымдар: жеңил горутиндер, операциялык тутумдун агымдарынан салыштырмалуу.
  • Көңүл буруу: тилге интеграцияланган пландоо параллелдүү программалоону жеңилдетет.