본문 바로가기

Code/go & python & java

[golang] 고루틴(Gorountine)

고루틴

고루틴. 지난번에 공부했는데 기억이 안나서 기록하면서 공부해보려 합니다.

고루틴은 여러함수를 병행(Concurrent)하게 실행할수 있는 논리적 가상 스레드 입니다.

비동기가 그것을 가능하게 해줍니다.

 

package main

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

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

func main() {
	for i := 0; i < 100; i++ {
		go hello(i)        // 고루틴 100개 생성 비동기 실행
	}

	fmt.Scanln()
}

 

위의 코드가 비동기가 아니면 얼마나 오래 걸릴지 생각을 해보면 됩니다.

메인함수 쓰레드 하나와, 고루틴 쓰레드 100개가 비동기로 병행.

고루틴 활용

고루틴이 모두 끝날 때까지 대기하는 기능이 있습니다.

 

package main

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

func hello(n int, w *sync.WaitGroup) {
    defer w.Done() // 끝났음을 전달
    r := rand.Intn(3)
    time.Sleep(time.Duration(r) * time.Second)
    fmt.Println(n)  
}

func main() {
    wait := new(sync.WaitGroup) //waitgroup 생성
    wait.Add(100) // 100개 기다릴꺼
    
    for i := 0; i < 100; i++ {
            go hello(i, wait) //wait을 매개변수로 전달
    }   
    
    wait.Wait() // 고루틴이 모두 끝날때까지 대기
}

 

메인함수 쓰레드 하나 대기, 고루틴 쓰레드 100개를 모두 끝날때까지 고루틴 100개를 모두 대기.

메인함수에 wait.Wait()가 없으면 먼저끝나서 프로그램이 종료되고,

add랑 done이 없으면, 고루틴이 몇개 기다려야하는지 모르니깐 바로 종료됩니다.

즉, Add, Done, Wait 는 한 세트입니다.

 

보통 고루틴을 익명함수로 만들어서 많이 사용합니다. 아래 예제처럼 (중요하진 않음) 이렇게 하면 절차적언어를 비동기식으로 짤수 있습니다. 익명함수가 왜 필요한지도 알 수 있었습니다. (익명함수클로져)

 

package main
 
import (
    "fmt"
    "sync"
)
 
func main() {
    var wait sync.WaitGroup
    wait.Add(102)
 
	str := "goorm!"
	
    go func() {
        defer wait.Done()
        fmt.Println("Hello")
    }()
	
	go func() {
        defer wait.Done()
        fmt.Println(str)
    }()
 
	for i := 0; i<100; i++ {
		go func(n int) {
			defer wait.Done()
			
			fmt.Println(n)
		}(i)
	}
 
    wait.Wait()
}

 

병행이 아닌 병렬처리

Concurrency 이 아닌 Parallelism 입니다.  특별한것 없습니다. 사용하고자 하는 CPU개수를 적으면 고루틴이 알아서 병렬로 처리됩니다  ㄷㄷㄷㄷ

 

package main

import (
	"fmt"
	"runtime"
	"sync"
)

func main() {
	fmt.Println("Velbie CPU", runtime.GOMAXPROCS(runtime.NumCPU()))
	var wait sync.WaitGroup
	wait.Add(100)

	for i := 0; i < 100; i++ {
		go func(n int) {
			defer wait.Done()
			fmt.Println(n)
		}(i)
	}
	wait.Wait()
}

 

참고 자료

구름에듀:

edu.goorm.io/learn/lecture/2010/%ED%95%9C-%EB%88%88%EC%97%90-%EB%81%9D%EB%82%B4%EB%8A%94-%EA%B3%A0%EB%9E%AD-%EA%B8%B0%EC%B4%88