프로그래밍/golang
ultimate in go-(9) 동시성(고루틴)
by 나도한강뷰
2023. 1. 26.
고루틴(goroutine)
go 스케쥴러
- go가 시작할때, 사용 가능 코어 개수를 확인한다.
- os 스레드 m개와 소프트웨어 스레드 n개를 잘 스케줄링하는것이 go runtime의 역할중 하나이다.
- 이러한 작동은 하이퍼스레딩, 코어당 스레드 수, 클럭 주기등의 요소를 반영하여서 작동한다.
- 작동방식 예시
- 프로세서 p는 os 스레드 m을 할당받아서 작동한다.
- 리눅스의 스케줄러에는 실행 대기열이 존재한다.(go에는 global run queue(GRQ)가 존재하며, p에는 local run queui(LRQ)가 존재한다.)
- go프로그램 시작시, 런타임은 고루틴을 생성한다.
- 특성 프로세서 p를 LRQ에 넣는다
- 고루틴은 스레드와 같이 sleeping, executing, runnable(하드웨어에 의해서 실행될때까지 대기)상태에 놓인다.
- 스레드를 스케쥴링하고 코어에서 실행하는건 os가 한다.
- 그 스레드위에서 다중화되어서 스케쥴링하는건 런타임이 한다.
- GRQ에 있는 애들을 꺼내서 LRQ에 할당후 실행요청한다.
- 이 대기열은 FIFO를 따르지 않는다.
- ultimate in go 한글번역이 약간 똥인거같다...
package main
import (
"fmt"
"runtime"
"sync"
)
func init() {
runtime.GOMAXPROCS(1)
}
func main() {
var wg sync.WaitGroup
wg.Add(2)
fmt.Println("Start Goroutines")
go func() {
lowercase()
wg.Done()
}()
go func() {
uppercase()
wg.Done()
}()
fmt.Println("Waiting To Finish")
wg.Wait()
fmt.Println("\nTerminating Program")
}
func lowercase() {
for count := 0; count < 3; count++ {
for r := 'a'; r <= 'z'; r++ {
fmt.Printf("%c ", r)
}
}
}
func uppercase() {
for count := 0; count < 3; count++ {
for r := 'A'; r <= 'Z'; r++ {
fmt.Printf("%c ", r)
}
}
}
Start Goroutines
Waiting To Finish
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z A B C D E F G H I J
K L M N O P Q R S T U V W X Y Z A B C D E F G H I J K L M N O P Q R S T
U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d
e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n
o p q r s t u v w x y z
Terminating Program