🔥 고루틴

420자
6분

고루틴(Goroutine)은 Go 런타임에 의해 관리되는 경량 스레드(Lightweight Thread)입니다. 다음과 같이 go 키워드를 사용하여 함수를 호출하면 새로운 고루틴을 시작할 수 있습니다.

go f(x, y, z)
 
go

f, x, y, z의 평가는 현재 고루틴에서 이루어지고, f의 실행은 새로운 고루틴에서 이루어집니다.

고루틴은 같은 주소 공간에서 실행되므로, 공유 메모리에 접근할 때는 동기화가 필요합니다. Go에서는 sync 패키지가 유용한 기본 요소를 제공하지만, 다른 기본 요소들도 있어서 많이 사용하진 않습니다.

다음은 고루틴을 사용하는 예제 코드입니다.

package main
 
import (
	"fmt"
	"time"
)
 
func say(s string) {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond) // 100밀리초 동안 일시 중지합니다.
		fmt.Println(s) // 문자열 s를 출력합니다.
	}
}
 
func main() {
	go say("world") // "world" 문자열을 출력하는 새로운 고루틴을 시작합니다.
	say("hello") // 메인 고루틴에서 "hello" 문자열을 출력합니다.
}
 
go

위 예제에서는 say 함수를 정의하고, main 함수에서 go 키워드를 사용하여 say 함수를 새로운 고루틴으로 실행합니다. 동시에 메인 고루틴에서도 say 함수를 호출하여 "hello"를 출력합니다.

고루틴은 매우 가볍고 효율적이어서, 수천 개의 고루틴을 동시에 실행할 수 있습니다. 이를 통해 Go는 동시성 프로그래밍을 쉽게 구현할 수 있게 해줍니다.

다음은 고루틴을 활용하여 동시성 프로그래밍을 구현한 예제입니다.

package main
 
import (
	"fmt"
	"sync"
	"time"
)
 
func worker(id int, wg *sync.WaitGroup) {
	defer wg.Done() // 함수 종료 시 WaitGroup의 카운터를 감소시킵니다.
 
	fmt.Printf("Worker %d starting\n", id) // 작업자의 시작을 알립니다.
 
	time.Sleep(time.Second) // 1초 동안 작업을 수행하는 것으로 가정합니다.
 
	fmt.Printf("Worker %d done\n", id) // 작업자의 종료를 알립니다.
}
 
func main() {
	var wg sync.WaitGroup // WaitGroup을 생성합니다.
 
	for i := 1; i <= 5; i++ {
		wg.Add(1) // WaitGroup의 카운터를 증가시킵니다.
		go worker(i, &wg) // 작업자 고루틴을 시작합니다.
	}
 
	wg.Wait() // 모든 작업자 고루틴이 종료될 때까지 대기합니다.
}
 
go

위 예제에서 sync.WaitGroup을 사용한 이유는 메인 고루틴이 작업자 고루틴들이 모두 종료될 때까지 기다리기 위해서입니다. 만약 wg.Wait()을 호출하지 않고 메인 고루틴이 먼저 종료된다면, 작업자 고루틴들이 실행 중인 상태에서 프로그램이 종료되어 버립니다.

이러한 경우에는 작업자 고루틴들의 실행 결과를 확인할 수 없게 되죠. 따라서 sync.WaitGroup을 사용하여 메인 고루틴이 작업자 고루틴들의 실행이 모두 끝날 때까지 대기하도록 해야 합니다.

만약 sync.WaitGroup을 사용하지 않는다면 다음과 같이 될 것입니다.

func main() {
	for i := 1; i <= 5; i++ {
		go worker(i, nil) // WaitGroup을 사용하지 않고 작업자 고루틴을 시작합니다.
	}
 
	// 메인 고루틴이 바로 종료됩니다.
}
 
go

이 경우에는 메인 고루틴이 작업자 고루틴들의 실행 결과를 기다리지 않고 바로 종료되어 버리기 때문에, 작업자 고루틴들의 실행 결과를 확인할 수 없습니다.

따라서 고루틴 간의 동기화를 위해서는 sync.WaitGroup이나 다른 동기화 기법을 사용하는 것이 필수적입니다. 이를 통해 고루틴들의 실행 순서를 제어하고, 필요한 결과를 얻을 수 있게 됩니다.

고루틴을 사용할 때는 항상 동기화 방법을 고려해야 한다는 점을 기억하시면 도움이 될 거예요!