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

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

Mary-Kate Olsen
Mary-Kate Olsen원래의
2024-10-29 20:38:29625검색

Why Does My Goroutine Incrementing a Variable Produce Unexpected Results?

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

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

<code class="go">package main

import "time"

func main() {
    i := 1
    go func() {
        for {
            i++
        }
    }()
    <-time.After(1 * time.Second)
    println(i)
}</code>

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

Go 메모리 모델

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

동기화 생략

주어진 코드에서:

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

컴파일러에 의한 최적화

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

<code class="go">for {}</code>

동기화 예시

문제가 발생했음을 보여주기 위해 동기화가 부족하므로 다음 코드를 고려하십시오.

<code class="go">package main

import (
    "sync"
    "time"
)

func main() {
    mx := new(sync.Mutex)
    i := 1
    go func() {
        for {
            mx.Lock()
            i++
            mx.Unlock()
        }
    }()
    <-time.After(1 * time.Second)
    mx.Lock()
    println(i)
    mx.Unlock()
}</code>

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

위 내용은 내 고루틴에서 변수를 증가시키면 예상치 못한 결과가 나타나는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.