"일꾼이 일을 잘하려면 먼저 도구를 갈고 닦아야 한다." - 공자, 『논어』.
첫 장 > 프로그램 작성 > 내 고루틴에서 변수를 증가시키면 예상치 못한 결과가 나타나는 이유는 무엇입니까?

내 고루틴에서 변수를 증가시키면 예상치 못한 결과가 나타나는 이유는 무엇입니까?

2024-11-05에 게시됨
검색:951

Why Does My Goroutine Incrementing a Variable Produce Unexpected Results?

이것은 컴파일러 최적화의 결과입니까?

이 코드 조각에서는 goroutine이 시작되고 변수 i를 반복적으로 증가시킵니다.

package main

import "time"

func main() {
    i := 1
    go func() {
        for {
            i  
        }
    }()
    

그러나 출력은 항상 1입니다. 이 동작은 Go 메모리 모델과 이 코드의 특정 구현에 기인할 수 있습니다.

Go 메모리 모델

Go 메모리 모델은 한 고루틴의 변수 읽기가 다른 고루틴의 동일한 변수에 대한 쓰기로 생성된 값을 관찰하도록 보장할 수 있는 조건을 정의합니다. 이는 공유 데이터에 대한 동시 액세스를 위한 동기화의 중요성을 강조합니다.

동기화 생략

주어진 코드에서:

  • i에 대한 할당(즉, i ) 동기화 이벤트 뒤에는 변경 사항이 다른 고루틴에 즉시 표시되지 않을 수 있음을 나타내는 동기화 이벤트가 뒤따르지 않습니다.
  • 컴파일러는 이 루프 최적화를 무작동으로 단순화하여 최적화할 수 있습니다.

컴파일러에 의한 최적화

공격적인 컴파일러는 i 문을 삭제하여 goroutine을 다음과 같이 효과적으로 줄일 수 있습니다.

for {}

동기화 예시

동기화 부족으로 인해 문제가 발생했음을 입증하려면 다음 코드를 고려하세요.

package main

import (
    "sync"
    "time"
)

func main() {
    mx := new(sync.Mutex)
    i := 1
    go func() {
        for {
            mx.Lock()
            i  
            mx.Unlock()
        }
    }()
    

이 경우 출력은 예상대로 더 이상 1이 아니라 큰 숫자입니다. sync.Mutex는 동기화를 제공하고 두 goroutine이 제어된 방식으로 i에 액세스하도록 보장하여 goroutine이 i를 증가시키고 변경 사항이 기본 루틴에 표시되도록 합니다.

최신 튜토리얼 더>

부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.

Copyright© 2022 湘ICP备2022001581号-3