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!
이 교착 상태가 발생하는 이유를 이해하려면 코드를 자세히 살펴보겠습니다.
문제는 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!