개발새발/Go

[Go] Goroutine

0xff 2024. 4. 15. 08:50

Golang에서 비동기 작업, 멀티스레드 활용을 위해서는 고루틴이 사용된다.

 

고루틴은 Thread보다 작은 단위이며, 런타임 내부에서 관리되기 때문에 

Thread보다 더 적은 리소스를 사용한다.

 

Ex 1. Async tasking

package main

import (
	"fmt"
	"math/rand"
	"time"
)

func hello(n int) {
	r := rand.Intn(100)
	time.Sleep(time.Duration(r))
	fmt.Println(n)
}

func main() {
	for i:=0; i < 100; i++ {
		go hello(i)
	}
	fmt.Scanln()
}

"go" 키워드를 사용해서 고루틴을 실행할 수 있다.

 

하지만 Golang은 기본적으로 단일 cpu만을 활용하도록 설정되어있다.

goroutine이 multi threading을 활용하게 하려면 GOMAXPROCS를 설정해주어야 한다.

 

Ex 2. Set GOMAXPROCS

package main

import (
	"fmt"
	"runtime"
)


func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	fmt.Println("CPU: ", runtime.GOMAXPROCS(0))
}

GOMAXPROCS에 args로 0을 넘기면 현재 값을 리턴해준다.

 

 

비동기적으로 task를 실행했으면 await도 가능해야 할 것이다.

이는 sync package의 WaitGroup을 사용해 구현이 가능하다.

 

Ex 3. async/await 패턴

package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"
)

func main() {
	wait := new(sync.WaitGroup)
	for i := 0; i < 10; i++ {
		wait.Add(1) // 기다릴 Goroutine 개수++
		go printRandom(i, wait) // waitGroup을 전달
	}
	wait.Wait() // 기다릴 Goroutine 개수가 0이 될 때 까지 block
}

func printRandom(idx int, wait *sync.WaitGroup) {
	defer wait.Done() // 함수가 종료되면 == Goroutine이 작업을 완료하면 기다릴 Goroutine 개수--
    randomSleepTime := rand.Intn(5)
	time.Sleep(time.Duration(randomSleepTime) * time.Second)
	fmt.Println(idx)
}

 

 

Refs:

https://artist-developer.tistory.com/14

https://pyrasis.com/book/GoForTheReallyImpatient/Unit33/01

https://velog.io/@314_dev/Go-비동기