- 책 또는 웹사이트의 내용을 복제하여 다른 곳에 게시하는 것을 금지합니다.
- 책 또는 웹사이트의 내용을 발췌, 요약하여 강의 자료, 발표 자료, 블로그 포스팅 등으로 만드는 것을 금지합니다.
채널 사용하기
이재홍 http://www.pyrasis.com 2014.12.17 ~ 2015.02.07
동기 채널
이번에는 동기 채널의 특성을 좀 더 자세히 알아보겠습니다. 다음은 고루틴과 메인 함수를 번갈아가면서 실행합니다.
package main
import (
"fmt"
"time"
)
func main() {
done := make(chan bool) // 동기 채널 생성
count := 3 // 반복할 횟수
go func() {
for i := 0; i < count; i++ {
done <- true // 고루틴에 true를 보냄, 값을 꺼낼 때까지 대기
fmt.Println("고루틴 : ", i) // 반복문의 변수 출력
time.Sleep(1 * time.Second) // 1초 대기
}
}()
for i := 0; i < count; i++ {
<-done // 채널에 값이 들어올 때까지 대기, 값을 꺼냄
fmt.Println("메인 함수 : ", i) // 반복문의 변수 출력
}
}
make(chan bool)처럼 채널을 생성합니다. 여기서는 채널로 값을 주고 받아도 실제로 사용하지 않으므로 자료형은 큰 의미가 없습니다. make 함수에 매개 변수를 하나만 지정했으므로 동기 채널을 생성됩니다. 비동기 채널과 버퍼는 뒤에서 설명하겠습니다.
먼저 고루틴을 생성하고, 반복문을 실행할 때마다 채널 done에 true 값을 보낸 뒤 1초를 기다립니다.
go func() {
for i := 0; i < count; i++ {
done <- true // 고루틴에 true를 보냄, 값을 꺼낼 때까지 대기
fmt.Println("고루틴 : ", i) // 반복문의 변수 출력
time.Sleep(1 * time.Second) // 1초 대기
}
}()
동기 채널이므로 done에 값을 보내면 다른 쪽에서 값을 꺼낼 때까지 대기합니다. 따라서 반복문도 실행되지 않으므로 "고루틴 : 숫자"가 계속 출력되지 않습니다.
이제 메인 함수에서는 반복문을 실행할 때마다 채널 done에서 값을 꺼냅니다.
for i := 0; i < count; i++ {
<-done // 채널에 값이 들어올 때까지 대기, 값을 꺼냄
fmt.Println("메인 함수 : ", i) // 반복문의 변수 출력
}
<-done 부분에서 채널에 값이 들어올 때까지 대기합니다. 먼저 앞의 고루틴에서 done에 값을 보냈기 때문에 값을 꺼낸 뒤 다음 코드로 진행합니다. 그리고 고루틴 쪽의 대기도 종료되면서 다시 반복문이 실행된 뒤 채널에 값을 보냅니다. 그리고 메인 함수는 채널에서 값을 꺼내고, 다시 고루틴도 채널에 값을 보냅니다. 따라서 다음과 같이 고루틴 → 메인 함수 → 고루틴 → 메인 함수 순서로 실행됩니다.
고루틴 : 0
메인 함수 : 0
고루틴 : 1
메인 함수 : 1
고루틴 : 2
메인 함수 : 2
그림 34-3 메인 함수와 고루틴 실행 순서
동기 채널은 보내는 쪽에서는 값을 받을 때까지 대기하고, 받는 쪽에서는 채널에 값이 들어올 때까지 대기합니다. 따라서, 동기 채널을 활용하면 고루틴의 코드 실행 순서를 제어할 수 있습니다.
저작권 안내
이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.- 블로그, 게시판 등에 퍼가는 것을 금지합니다.
- 비공개 포스트에 퍼가는 것을 금지합니다.
- 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
- 링크 및 SNS 공유는 허용합니다.