반응형
주의
반복문에서 고루틴을 돌리면 신기하게 결과물이 나올 때가 있습니다.
아래 코드를 실행했을 때의 결과는 무엇일까요?
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
for _, text := range []string{"a", "b", "c"} {
wg.Add(1)
go func() {
defer wg.Done()
fmt.Println(text)
}()
}
wg.Wait()
}
만약 a, b, c가 랜덤으로 출력 것이라 생각하신다면 틀렸습니다
결과는 아래와 같습니다.
c
c
c
왜 이런 일이
이유는 루프문이 고루틴보다 먼저 끝나서 고루틴에서 사용할 수 있도록 메모리를 힙으로 옮겼기 때문입니다.
즉 for문이 먼저 끝나서 text의 값은 마지막 c를 가리키기에 이런 일이 발생한 것입니다.
참고로
※ 힙(Heap) : 동적으로 메모리를 할당한 부분, 사용자가 직접 할당 및 해제를 해야 함, 일반적으로 프로그램 실행 중의 생기고 제거됨
※ 스택(Stack) : 함수 내의 지역 변수 및 매개변수를 저장하며 LIFO으로 동작하며 해당 함수가 종료 시 제거함
해결법
해결법은 간단합니다, 고루틴이 실수로 할당이 해제되어야 하는 변수에 접근하지 못하도록 메모리에 값이 고정된 변수를 접근하게 수정하면 됩니다.
해당 기능은 이미 지원하고 있습니다.
아래 코드로 수정해 봅시다.
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
for _, text := range []string{"a", "b", "c"} {
wg.Add(1)
// 고루틴 함수에서 매개변수를 받도록 바꿈
go func(text string) {
defer wg.Done()
fmt.Println(text)
}(text)
}
wg.Wait()
}
위 코드처럼 간단하게 매개변수로 받게 수정함으로써 해결할 수 있습니다.
고루틴은 이것 외에도 주의해야 하는 점이 여러 개 있습니다.
아래는 동시성 환경에서 발생하는 문제점입니다, 보시고 도움이 되었으면 좋겠습니다.
위 글의 제목처럼 동시성 문제를 해결하기 위해서는 공유 메모리에 대해서
동기화된 접근만 하거나 고의 CSP( Communicating Sequential Processes ) 기본요소를 사용하면 됩니다.
- Goroutine
- Channel
- Select
- Mutex
- WaitGroup
반응형
'Go Lang > Study' 카테고리의 다른 글
[GoLang] GraphQL API 만들기 part 1 (라이브러리 탐색) (38) | 2024.03.01 |
---|---|
[GoLang] GoLang 면접 질문 정리 (2) | 2024.02.26 |
[GoLang] Go에서 동시성이란 (1) | 2024.01.15 |
[GoLang] 데드락, 라이브락, 기아상태 이해하기 (Deadlock, Livelock, Starvation) (1) | 2024.01.02 |
[GoLang] Context가 뭘까요? (2) | 2023.12.02 |