관리 메뉴

JHLBLUE

Goroutine 본문

개발/GO

Goroutine

JHLBLUE 2023. 1. 10. 01:43

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 이후의 코드가 실행되는 것을 확인

Comments