JHLBLUE
Goroutine 본문
1. Goroutine 사용하기
Goroutine은 Go에서 사용하는 경량화된 쓰레드로, 병렬 작업을 처리할 때 사용할 수 있음(링크)
사용법 : go <함수이름>
예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
package main
import (
"fmt"
"time"
)
func test(s string) {
for i := 0; i < 5; i++ {
fmt.Println("test() called")
fmt.Println(s)
time.Sleep(100 * time.Millisecond)
}
}
func main() {
go test("call with goroutine")
test("call without goroutine")
}
|
cs |
결과

2. sync 사용하기
Goroutine 등의 쓰레드에서 상호 배제(Mutex)를 적용하기 위해 sync 패키지를 사용(링크)
- Mutex
동시에 2개 이상의 프로세스 또는 쓰레드가 접근하면 안되는 영역을 지정하기 위해 사용
Lock() : 임계 영역의 시작 부분을 지정할 때 호출
Unlock() : 임계 영역의 종료 부분을 지정할 때 호출
비교코드
Mutex 없는 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
package main
import (
"fmt"
"time"
)
var count = 0
func test(s string) {
fmt.Println("test() called")
if s != "test" {
count++
fmt.Println("count in test()")
fmt.Println(count)
}
time.Sleep(50 * time.Millisecond)
}
func main() {
time.Sleep(5 * time.Millisecond)
for i := 0; i < 1000; i++ {
go test("call with goroutine")
}
test("test")
fmt.Println("count in main()")
fmt.Println(count)
}
|
cs |
결과

Mutex 적용한 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
package main
import (
"fmt"
"sync"
"time"
)
var count = 0
func test(s string) {
mutex := &sync.Mutex{}
mutex.Lock()
fmt.Println("test() called")
if s != "test" {
count++
fmt.Println("count in test()")
fmt.Println(count)
}
time.Sleep(50 * time.Millisecond)
mutex.Unlock()
}
func main() {
time.Sleep(5 * time.Millisecond)
for i := 0; i < 1000; i++ {
go test("call with goroutine")
}
test("test")
fmt.Println("count in main()")
fmt.Println(count)
}
|
cs |
결과
count 변수에 값을 더하는 영역에 Mutex로 임계 영역이 설정되어 있으므로, 이전 쓰레드의 작업이 완료된 이후에 다음 쓰레드가 코드를 실행함

- WaitGroup
goroutine 그룹이 완료될 때 까지 대기하도록 설정하는 코드
Add() : WaitGroup 카운터에 값을 파라미터만큼 추가
Done() : WaitGroup 카운터에 값을 1 감소
Wait() : WaitGroup 카운터의 값이 0이 될 때 까지 대기
예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
package main
import (
"fmt"
"sync"
"time"
)
var count = 0
func main() {
var waitgroup sync.WaitGroup
time.Sleep(5 * time.Millisecond)
for i := 0; i < 1000; i++ {
waitgroup.Add(1)
go func(s string) {
fmt.Println(s)
count++
fmt.Printf("%d\n", count)
defer waitgroup.Done()
}("call with goroutine")
}
waitgroup.Wait()
fmt.Println("count in main()")
fmt.Println(count)
}
|
cs |
결과
goroutine이 모두 완료된 이후에, Wait 이후의 코드가 실행되는 것을 확인
