Golang에는 Go Routine(이하 "고루틴")으로 불리는 동시성 예약어가 있다.
즉, main 함수를 돌리면서 순차적이 아니라 익명함수나 함수를 동시에 실행시킬 수 있다는 뜻이다.
바로 아래 예제를 살펴보자.
// Go Routine
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
var cnt int = 10
var n int = 1
for i := 0; i < 10; i++ {
wg.Add(1)
go func(n int) {
defer wg.Done()
cnt--
switch n {
case 1:
fmt.Println("I'm", n, "st Go Routine! :D and now cnt is:", cnt)
case 2:
fmt.Println("I'm", n, "nd Go Routine! :D and now cnt is:", cnt)
case 3:
fmt.Println("I'm", n, "rd Go Routine! :D and now cnt is:", cnt)
default:
fmt.Println("I'm", n, "th Go Routine! :D and now cnt is:", cnt)
}
}(n)
n++
}
wg.Wait()
fmt.Println("cnt is now: ", cnt)
}
위 소스 코드를 보면, 단순히 cnt라는 변수를 10에서 0까지 1씩 빼는 역할을 한다.
하지만 우리는 중요한 것을 아래 소스 코드 실행 결과에서 알 수 있다.
I'm 3 rd Go Routine! :D and now cnt is: 3
I'm 5 th Go Routine! :D and now cnt is: 5
I'm 1 st Go Routine! :D and now cnt is: 9
I'm 2 nd Go Routine! :D and now cnt is: 8
I'm 6 th Go Routine! :D and now cnt is: 7
I'm 4 th Go Routine! :D and now cnt is: 6
I'm 8 th Go Routine! :D and now cnt is: 2
I'm 9 th Go Routine! :D and now cnt is: 1
I'm 7 th Go Routine! :D and now cnt is: 0
I'm 10 th Go Routine! :D and now cnt is: 4
cnt is now: 0
위는 필자가 해당 소스 코드를 실행시켰을 때 얻은 결과였다.
사람마다 결과는 다 다를 수 있다. 오히려 필자와 같기가 더 힘들 것이다.
필자도 소스 코드를 실행할 때마다 결과가 달라진다.
원래 전통적인 절차지향 언어에서는, 똑같은 기능을(cnt를 10에서 0까지 1씩 뺌) 하는 소스 코드에서 다음과 같은 실행 결과를 냈을 것이다.
I'm 1 st Go Routine! :D and now cnt is: 9
I'm 2 nd Go Routine! :D and now cnt is: 8
I'm 3 rd Go Routine! :D and now cnt is: 7
I'm 4 th Go Routine! :D and now cnt is: 6
I'm 5 th Go Routine! :D and now cnt is: 5
I'm 6 th Go Routine! :D and now cnt is: 4
I'm 7 th Go Routine! :D and now cnt is: 3
I'm 8 th Go Routine! :D and now cnt is: 2
I'm 9 th Go Routine! :D and now cnt is: 1
I'm 10 th Go Routine! :D and now cnt is: 0
cnt is now: 0
1번부터 10번까지의 익명함수들이 차례대로 접근을 하고, cnt는 10부터 0까지 차례대로 떨어질 것이다.
하지만 Golang에서 고루틴을 사용한 결과,
고루틴의 접근 순서는 1 → 2 → 6 → 4 → 5 → 10 → 3 → 8 → 9 → 7 이었으며,
고루틴의 출력 순서는 3 → 5 → 1 → 2 → 6 → 4 → 8 → 9 → 7 → 10 이었다.
이는 고루틴이 접근 순서가 달라도, 병목(Deadlock) 현상이나 막힘(Block) 현상 발생시 같은 스레드 내에서 타 고루틴으로 분기하는 연산을 하는 것으로 설명될 수 있다.
(이에 대한 더 자세한 설명은 심화편에서 다뤄지고 있다.)
(해당 링크: 2020/01/12 - [IT/Go 언어 (Golang)] - [Golang] Go Routine (고 루틴) - Golang의 꽃 [심화])
이러한 고루틴의 동시성을 이용하면,
이벤트 분산처리나 거대한 프로그램의 가속화를 이뤄볼 수 있다.
물론, 위에 나온대로 접근 순서와 실행 순서가 다를 수 있으므로 해당 순서가 중요하다면 sync.Wait() 함수 등으로 정확히 묶어 순서가 어긋나지 않도록 해야 한다.
그렇지 않으면 Fatal Error를 뿜어낼테니...
'IT > Go 언어 (Golang)' 카테고리의 다른 글
[Golang] 자체 MQTT 브로커 서버 구현 - 1 (2) | 2020.02.26 |
---|---|
[Golang] 고루틴과 채널(chan)을 이용한 피보나치 수열 (0) | 2020.01.12 |
[Golang] Go Routine (고 루틴) - Golang의 꽃 [심화] (0) | 2020.01.12 |
[Golang] 문자열과 문자열의 종류 (0) | 2019.12.22 |
[Golang] 데이터 타입 (자료형) (0) | 2019.12.22 |