>백엔드 개발 >Golang >Go에서 WaitGroup을 값으로 전달하면 교착 상태가 발생하는 이유는 무엇이며 어떻게 해결할 수 있나요?

Go에서 WaitGroup을 값으로 전달하면 교착 상태가 발생하는 이유는 무엇이며 어떻게 해결할 수 있나요?

Linda Hamilton
Linda Hamilton원래의
2024-10-28 18:56:29617검색

Why does passing a WaitGroup by value in Go lead to a deadlock, and how can it be resolved?

Go 채널의 교착 상태: 가변 범위의 문제

Golang 프로그램에서 채널은 고루틴 간의 통신을 용이하게 합니다. 그러나 채널을 잘못 사용하면 아래 코드에서 볼 수 있듯이 교착 상태가 발생할 수 있습니다.

<br>package main</p>
<p>import(</p>
<pre class="brush:php;toolbar:false">"fmt"
"sync"

)

func push(c chan int, wg sync.WaitGroup) {

for i := 0; i < 5; i++ {
    c <- i
}
wg.Done()

}

func pull(c chan int, wg sync.WaitGroup) {

for i := 0; i < 5; i++ {
    result, ok := <-c
    fmt.Println(result, ok)
}
wg.Done()

}

func main() {

var wg sync.WaitGroup
wg.Add(2)
c := make(chan int)

go push(c, wg)
go pull(c, wg)

wg.Wait() // Block the main thread until goroutines complete

}

이 프로그램을 실행할 때 다음과 같은 문제가 발생할 수 있습니다. 다음 오류:

fatal error: all goroutines are asleep - deadlock!

이 교착 상태가 발생하는 이유를 이해하려면 코드를 자세히 살펴보겠습니다.

  • main은 WaitGroup, 채널 c 및 푸시 및 풀용 고루틴을 생성합니다.
  • 푸시 및 풀 함수는 WaitGroup을 사용하여 실행을 동기화합니다.
  • 푸시 함수는 루프의 c에 값을 보내고 wg.Done()을 호출하여 완료 신호를 보냅니다.
  • pull 함수는 c에서 값을 받아 인쇄합니다. 또한 wg.Done()을 사용하여 완료 신호를 보냅니다.

문제는 WaitGroup이 고루틴에 전달되는 방식에 있습니다. 앰퍼샌드(&) 없이 값이 전달되면 참조가 아닌 값으로 전달됩니다. 이 경우 각 고루틴에 대해 WaitGroup의 복사본이 생성됩니다.

결과적으로 각 고루틴이 wg.Done()을 호출하면 WaitGroup의 로컬 복사본이 수정됩니다. 메인 스레드는 wg가 모든 고루틴이 완료되었음을 나타낼 때까지 기다리므로 두 고루틴 모두 원래 WaitGroup을 업데이트하지 않기 때문에 무한정 기다립니다. 이로 인해 교착 상태가 발생합니다.

이 문제를 해결하려면 WaitGroup을 참조로 전달해야 합니다. 이렇게 하면 두 고루틴이 모두 WaitGroup의 동일한 인스턴스를 수정하고 완료를 메인 스레드에 올바르게 알릴 수 있습니다.

수정 사항이 포함된 개정된 코드 버전은 다음과 같습니다.

<br>패키지 메인</p>
<p>import (</p>
<pre class="brush:php;toolbar:false">"fmt"
"sync"

)

func push(c chan int, wg *sync.WaitGroup) {

for i := 0; i < 5; i++ {
    c <- i
}
wg.Done()

}

func pull(c chan int, wg *sync.WaitGroup) {

for i := 0; i < 5; i++ {
    result, ok := <-c
    fmt.Println(result, ok)
}
wg.Done()

}

func main() {

var wg sync.WaitGroup
wg.Add(2)
c := make(chan int)

go push(c, &wg) // Pass the WaitGroup by reference using the ampersand
go pull(c, &wg) // Pass the WaitGroup by reference using the ampersand

wg.Wait()

}

WaitGroup을 참조로 전달함으로써 메인 스레드가 두 고루틴이 작업을 완료한 시기를 올바르게 판단하여 교착 상태를 피할 수 있도록 보장합니다.

위 내용은 Go에서 WaitGroup을 값으로 전달하면 교착 상태가 발생하는 이유는 무엇이며 어떻게 해결할 수 있나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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