>  기사  >  백엔드 개발  >  Go에서 WaitGroups 및 버퍼링된 채널을 사용할 때 교착 상태가 어떻게 발생할 수 있나요?

Go에서 WaitGroups 및 버퍼링된 채널을 사용할 때 교착 상태가 어떻게 발생할 수 있나요?

Linda Hamilton
Linda Hamilton원래의
2024-10-28 04:16:30667검색

How Can Deadlock Occur When Using WaitGroups and Buffered Channels in Go?

WaitGroups를 사용한 Go 동시성 교착 상태 감지

Go에서는 고루틴을 조정하기 위해 채널 및 대기 그룹을 사용하여 동시성을 관리하는 경우가 많습니다. 그러나 교착 상태로 이어질 수 있는 잠재적 위험을 이해하는 것이 중요합니다.

문제 설명

버퍼 채널 및 대기 그룹을 사용하려고 시도하는 다음 코드를 고려하세요.

<code class="go">package main

import (
    "fmt"
    "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 // Send to channel
            return
        }()
    }
    wg.Wait() // Wait for all goroutines to complete

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

용량에 도달하면 채널이 자동으로 닫힐 것으로 예상했음에도 불구하고 이 코드는 예기치 않게 교착 상태 오류를 발생시킵니다.

해결 방법

두 가지가 있습니다. 교착 상태로 이어지는 주요 문제:

  1. 채널 용량 부족: 채널 버퍼의 용량은 4인데, 쓰기를 시도하는 고루틴이 5개 있습니다. 이로 인해 채널이 가득 차서 쓰기를 기다리는 고루틴이 차단되는 상황이 발생합니다.
  2. Range Over Unclosed Channel: c := range ch에 대한 루프는 계속해서 채널에서 들어오는 요소를 수신합니다. 채널이 닫힐 때까지 무기한 대기 중입니다. 그러나 채널에 쓸 고루틴이 남아 있지 않기 때문에 채널은 절대 닫히지 않습니다.

교착 상태를 해결하기 위한 두 가지 솔루션은 다음과 같습니다.

솔루션 1: 채널 용량 확장 및 명시적 닫기

<code class="go">ch := make(chan []int, 5) // Increase channel capacity
...
wg.Wait()
close(ch) // Close the channel to stop range loop</code>

이렇게 하면 채널에 충분한 공간이 확보되고 명시적으로 닫혀 범위 루프가 종료될 수 있습니다.

해결책 2: 고루틴의 완료 조건 신호

<code class="go">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() {
            ch <- m
            wg.Done() // Signal completion within goroutine
            return
        }()
    }
    go func() {
        for c := range ch {
            fmt.Printf("c is %v\n", c)
            wg.Done() //Decrement count for each iteration
        }
    }()
    wg.Wait()
}</code>

이 솔루션에서 각 고루틴은 고루틴 자체 내에서 wg.Done()을 호출하여 완료를 알립니다. 또한 대기 그룹은 각 반복마다 범위 루프 내에서 감소하여 wg.Wait()가 결국 완료되고 프로그램이 종료되도록 합니다.

위 내용은 Go에서 WaitGroups 및 버퍼링된 채널을 사용할 때 교착 상태가 어떻게 발생할 수 있나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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