Notice
Recent Posts
Recent Comments
Link
«   2024/06   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
Archives
Today
Total
관리 메뉴

Code Habit

[Go언어] Go루틴 ( 경량 쓰레드 ) 본문

카테고리 없음

[Go언어] Go루틴 ( 경량 쓰레드 )

코드베어 2022. 11. 21. 22:24

C++ 개발을 하면서 여러 일을 동시에 처리해야 할때 멀티 쓰레드를 사용하여 처리한다. 이때 여러 쓰레드에서 동시에 일을 처리하기 위해 코어에서 쓰레드 사이를 옮겨다니며 컨텍스트 스위칭이 발생하는데 이는 자칫하면 부하를 일으켜 성능 저하를 유발하곤 한다. 하여 Go언어에서는 컨텍스트 스위칭 비용을 절약하기 위해 Go루틴이라는 Go 런타임에서 직접 관리하는 경량쓰레드를 제공한다.

 

Go루틴은 명령을 수행하는 단일 흐름으로 OS 스레드를 이용하는 경량 스레드이다. Go언어는 CPU 코어, OS 스레드, 소루틴을 서로 조율하여 사용해 고루틴을 효율적으로 다룬다. 고루틴을 이용하면 코어와 스레드는 변경되지 않고 오직 고루틴만 옮겨 다니기 때문에 컨텍스트 스위칭이 일어나지 않는다. 

OS 스레드를 직접 사용하는 다른 언어에서는 스레드 개수가 많아지면 컨텍스트 스위칭 비용이 증가되기 때문에 프로그램 성능이 떨어지지만 Go 언어에서는 고루틴이 증가되어도 컨텍스트 스위칭 비용이 발생하지 않기 때문에 수백, 수천 고루틴을 마음껏 만들어서 쓸 수 있다. 

 

Go루틴은 OS 쓰레드보다 훨씬 가볍게 비동기 처리를 구현하기 위해 만든 것으로, Go 런타임이 자체 관리한다. Go 루틴은 OS 쓰레드와 1:1로 대응하지 않고 Multiplexing으로 훨씬 적은 OS 쓰레드를 사용한다. 메모리 측면에서도 효율적이고 필요하면 동적으로 늘려 사용한다.

 

네트워크 대기 상태 등의 Go루틴에 CPU 코어와 OS 쓰레드가 할당되면 CPU 자원 낭비가 발생한다. 그래서 Go 언어에서는 이런 상태에 들어간 루틴을 대기 상태로 보내고, 실행을 기다리는 다른 루틴에 CPU코어와 OS스레드를 할당하여 실행할 수 있게 한다.

 

Go루틴 사용 예제이다.

var wg sync.WaitGroup

func SumAtoB(a, b int) {
	sum := 0
	for i := a; i <= b; i++ {
		sum += i
	}
	fmt.Printf("%d부터 %d까지 합계는 %d입니다.\n", a, b, sum)
	wg.Done() // 1개의 작업 완료를 의미
}

func main() {
	wg.Add(10) // 작업 개수 설정
	for i := 0; i < 10; i++ {
		go SumAtoB(1, 10000000)		// go 루틴으로 SumAtoB 함수 실행 : 실행 후 바로 넘어간다.
	}

	wg.Wait() // 작업이 완료될때까지 기다린다.
}

 

** 출처 : Tucker이 Go언어 프로그래밍