>  기사  >  백엔드 개발  >  WaitGroup 및 버퍼링된 채널과 함께 제공된 Go 코드로 인해 교착 상태가 발생하는 이유는 무엇입니까?

WaitGroup 및 버퍼링된 채널과 함께 제공된 Go 코드로 인해 교착 상태가 발생하는 이유는 무엇입니까?

Barbara Streisand
Barbara Streisand원래의
2024-10-26 22:08:02680검색

Why does the provided Go code with WaitGroup and buffered channel result in a deadlock?

WaitGroup 및 버퍼 채널을 사용한 Go의 교착 상태

Go에서는 여러 고루틴이 서로 완료되기를 기다릴 때 교착 상태가 발생합니다. 교착 상태에 빠졌습니다. 이러한 상황은 버퍼링된 채널과 WaitGroups를 잘못 사용할 때 발생할 수 있습니다.

다음 코드를 고려하세요.

<code class="go">package main

import "fmt"
import "sync"

func main() {
    ch := make(chan []int, 4)
    var m []int

    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            ch <- m
            return
        }()
    }
    wg.Wait()

    for c := range ch {
        fmt.Printf("c is %v", c)
    }
}</code>

이 코드는 버퍼 크기가 4인 채널을 만들고 5개의 고루틴을 시작할 것으로 예상됩니다. , 각각은 빈 조각을 채널로 보냅니다. 메인 고루틴은 모든 고루틴이 완료될 때까지 기다린 다음 채널 전체를 탐색합니다.

그러나 이 코드는 교착 상태를 초래합니다. 왜?

교착 상태의 원인:

코드에 두 가지 문제가 있습니다.

  1. 채널 용량: 채널의 용량은 4는 최대 4개의 요소를 담을 수 있다는 의미입니다. 그러나 채널로 전송을 시도하는 고루틴이 5개 있어서 마지막 고루틴이 슬롯이 해제되기를 기다리며 차단되는 상황이 발생합니다.
  2. 채널 닫기: 범위 ch 루프는 계속해서 요소를 기다립니다. 채널에 들어가려면. 채널에 쓸 고루틴이 더 이상 남아 있지 않으므로 루프는 무기한 대기합니다.

해결책:

  1. 채널 용량 증가: 채널 용량을 5로 늘리면 모든 고루틴이 차단 없이 값을 전송할 수 있는 충분한 슬롯을 사용할 수 있습니다. 또한, 고루틴 쓰기가 완료된 후 채널을 닫으면 범위 루프에 더 이상 요소가 오지 않는다는 신호가 전달되어 무한정 기다리지 않게 됩니다.

    <code class="go">ch := make(chan []int, 5)
    ...
    wg.Wait()
    close(ch)</code>
  2. 완료 사용 () 루프 내: 채널을 닫는 대신 WaitGroup의 Done() 메서드를 사용하여 마지막 고루틴이 완료되면 신호를 보낼 수 있습니다. 범위 루프 내에서 Done()을 호출하면 채널이 비어 있고 루프가 종료될 수 있을 때 기본 고루틴에 알림이 전달됩니다.

    <code class="go">go func() {
        for c := range ch {
            fmt.Printf("c is %v\n", c)
            wg.Done()
        }
    }()
    wg.Wait()</code>

이 솔루션은 다음을 보장하여 교착 상태를 해결합니다. 채널의 용량이 충분하고 채널에서 더 이상 읽을 요소가 없으면 범위 루프가 종료됩니다.

위 내용은 WaitGroup 및 버퍼링된 채널과 함께 제공된 Go 코드로 인해 교착 상태가 발생하는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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