Go는 User Thread레벨을 Goroutine으로서 지원한다 또한 각 Goroutine끼리의 메시지 교환기법도 제공해주는데 이를 Channel이라고 한다
Process는 크게 Local queue와 Global queue를 통해 Goroutine을 가져오게 되는데 우선순위에 따라 Local queue부터 들고온다는 점을 먼저 기억해두자
func GoChat() {
c := make(chan string)
for i := 0; i < 10; i++ {
go func() {
c <- "Hello, World!" + strconv.Itoa(i)
}()
println(<-c)
}
}
메인 고루틴이 진행을 하다 새로운 고루틴으로 컨텍스트 스위칭이 일어나고 c <- 을 통해 실제 채널에 값을 발신하는 순간
해당 고루틴은 park된 상태로 전환된다 이 때 이 고루틴은 idle상태가 아닌 잠깐 block된 상태로 넘어가게 된다
그리고 원래 메인 고루틴으로 돌아와 <-c구문을 만나는 순간 park된 고루틴을 unpark시키고 이는 Local queue의 Head로 적재된다
이 후 메인 고루틴에 의해 해당 고루틴이 다시 불려와져 println되는 방식으로 진행된다
이렇게 총 10번을 반복하면 for문을 빠져나와 메인 프로세스가 종료된다
즉 여기서의 핵심은 Main goroutine은 스케쥴링의 역할을 도맡으며 각 고루틴들은 park -> unpark -> run이 세가지의 동작을 반복하면서 메시지를 수신 및 발신한다
실제 위 코드를 실행해보면
다음과같이 스케쥴링 고루틴과 서브 고루틴이 반복적으로 실행되는걸 볼 수 있다