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 менен байланышкан жана жергиликтүү кезектеги же глобалдык кезектеги горутиндерди аткарат.
Ишке ашыруу принциби:
- Жаңы горутина түзүлүп, жеткиликтүү Pнин жергиликтүү кезегине коюлат.
- P менен байланышкан M жергиликтүү кезектен горутинаны алат жана аткарат.
- Эгер жергиликтүү кезек бош болсо, M башка Pлердөн горутиналарды уурдап алууга аракет кылат.
- Эгер P блоктосо (мисалы, системдик чакырууда), ага байланышкан M ажыратылып, башка M ошол P менен байланышат. Блоктогон M кайра колдонулушу мүмкүн, системдик чакыруудан кийин.
- Эгер горутина канал же мунайтексте блоктосо, ал күтүүлөр кезегине коюлат, жана планалоочу ошол Mде башка горутинаны аткарууга тандайт.
- Планалоочу узак убакыт иштеген горутиналарды алдын алуу үчүн мезгил-мезгили менен текшерүүлөрдү жүргүзөт, башка горутиналарга аткаруу убактысын берет.
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 планалоочуусу бул горутиндерди операциялык тутумдун жеткиликтүү агымдарына бөлүштүрөт, жергиликтүү жана мүмкүн болсо глобалдык кезектерди колдонуп, ошондой эле "уурдап алуу" механизмин колдонулат.
Бул ыкманын артыкчылыктары:
- Масштабдуулук: көпядролук системдердин эффективдүү колдонулушу.
- Төмөн чыгымдар: жеңил горутиндер, операциялык тутумдун агымдарынан салыштырмалуу.
- Көңүл буруу: тилге интеграцияланган пландоо параллелдүү программалоону жеңилдетет.