동기화 객체 사용하기

이재홍 http://www.pyrasis.com 2014.12.17 ~ 2015.02.07

대기 그룹 사용하기

대기 그룹은 고루틴이 모두 끝날 때까지 기다릴 때 사용합니다. 앞에서는 time.Sleep, fmt.Scanln 함수를 사용하여 고루틴이 끝날 때까지 임시로 대기했습니다. 이번에는 대기 그룹을 사용하여 고루틴이 끝날 때까지 기다려보겠습니다.

sync 패키지에서 제공하는 대기 그룹의 구조체와 함수는 다음과 같습니다.

  • sync.WaitGroup
  • func (wg *WaitGroup) Add(delta int): 대기 그룹에 고루틴 개수 추가
  • func (wg *WaitGroup) Done(): 고루틴이 끝났다는 것을 알려줄 때 사용
  • func (wg *WaitGroup) Wait(): 모든 고루틴이 끝날 때까지 기다림
package main

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

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU()) // 모든 CPU 사용

	wg := new(sync.WaitGroup) // 대기 그룹 생성

	for i := 0; i < 10; i++ {
		wg.Add(1)            // 반복할 때마다 wg.Add 함수로 1씩 추가
		go func(n int) {     // 고루틴 10개 생성
			fmt.Println(n)
			wg.Done()    // 고루틴이 끝났다는 것을 알려줌
		}(i)
	}

	wg.Wait() // 모든 고루틴이 끝날 때까지 기다림
	fmt.Println("the end")
}

대기 그룹은 sync.WaitGroup을 할당 한 뒤에 Add, Done, Wait 함수로 사용합니다. 고루틴을 생성할 때 Add 함수로 고루틴 개수를 추가해줍니다. 그리고 고루틴 안에서 Done 함수를 사용하여 고루틴이 끝났다는 것을 알려줍니다. 마지막으로 Wait 함수를 사용하여 모든 고루틴이 끝날 때까지 기다립니다.

Add 함수에 설정한 값과 Done 함수가 호출되는 횟수는 같아야 합니다. 즉 Add(3)으로 설정했다면 Done 함수는 3번 호출되야 합니다. 이 횟수가 맞지 않으면 패닉이 발생하므로 주의합니다.

Done 함수는 다음과 같이 defer와 함께 사용해서 지연 호출로도 사용할 수 있습니다.

for i := 0; i < 10; i++ {
	wg.Add(1)
	go func(n int) {
		defer wg.Done() // 고루틴이 끝나기 직전에 wg.Done 함수 호출
		fmt.Println(n)
	}(i)
}

저작권 안내

이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.
  • 블로그, 게시판 등에 퍼가는 것을 금지합니다.
  • 비공개 포스트에 퍼가는 것을 금지합니다.
  • 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
  • 링크 및 SNS 공유는 허용합니다.

Published

01 June 2015