이 기사에서는 "교착 상태"의 원인을 분석해 보겠습니다. 다음 코드 조각에서 Go 채널과 관련된 교착 상태 상황에서 발생하는 오류:
package main import ( "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() }
이 코드를 실행할 때 다음 오류가 발생합니다.
throw: all goroutines are asleep - deadlock!
이 코드의 sync.WaitGroup과 같은 구조체가 참조가 아닌 값으로 전달되기 때문에 교착 상태가 발생합니다. 이는 WaitGroup을 함수(푸시 및 풀)에 전달할 때 실제로 원래 개체 대신 WaitGroup의 복사본을 전달한다는 의미입니다.
결과적으로 각 함수는 자체 복사본에서 작동합니다. WaitGroup의 것이며 wg.Done()을 호출하면 자신의 복사본이 감소합니다. 이는 기본 고루틴이 기다리고 있는 원래 WaitGroup을 업데이트하지 않으므로 교착 상태가 발생합니다.
이 문제를 해결하려면 포인터를 전달해야 합니다. 값 대신 WaitGroup에 추가합니다. 이렇게 하면 푸시 및 풀 기능이 모두 WaitGroup의 동일한 인스턴스에서 작동하고 wg.Done()에 대한 호출이 원래 객체에 영향을 미치게 됩니다.
수정된 코드 버전은 다음과 같습니다.
package main import ( "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() }
이렇게 변경하면 이제 WaitGroup에 대한 포인터를 함수에 전달하여 둘 다 동일한 개체에서 작업하고 해당 상태를 올바르게 업데이트하도록 할 수 있습니다. 이를 통해 교착 상태 상황이 제거되고 프로그램이 오류 없이 실행될 수 있습니다.
위 내용은 sync.WaitGroup을 사용할 때 Go 채널에서 교착 상태 오류를 수정하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!