>백엔드 개발 >Golang >Go에서 버퍼링되지 않은 채널이 교착 상태를 일으키는 이유는 무엇입니까?

Go에서 버퍼링되지 않은 채널이 교착 상태를 일으키는 이유는 무엇입니까?

Mary-Kate Olsen
Mary-Kate Olsen원래의
2024-12-21 17:31:11170검색

Why Do Unbuffered Channels in Go Cause Deadlocks?

고루틴에서 버퍼링되지 않은 채널의 교착 상태

Go의 동시성 모델 내에서 버퍼링되지 않은 채널은 예상치 못한 교착 상태로 이어질 수 있습니다. 왜 이런 일이 발생하는지 자세히 알아보고 대체 솔루션을 찾아보겠습니다.

다음 코드 조각을 고려해 보세요.

package main

import "fmt"

func main() {
    c := make(chan int)    
    c <- 1   
    fmt.Println(<-c)
}

이 코드는 버퍼링되지 않은 채널에서 간단한 보내기 및 받기 작업을 수행하는 것처럼 보입니다. 그러나 실행하면 다음 오류와 함께 교착 상태가 발생합니다.

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
    /home/tarrsalah/src/go/src/github.com/tarrsalah/tour.golang.org/65.go:8 +0x52
exit status 2

이 교착 상태가 발생하는 이유를 이해하려면 먼저 버퍼링되지 않은 채널의 동작을 이해해야 합니다.

버퍼링되지 않은 채널 탐구

Go의 공식 문서에 설명된 대로 "만약 채널이 버퍼링되지 않은 경우 송신자는 수신자가 값을 수신할 때까지 차단합니다. 채널에 버퍼가 있으면 송신자는 값이 버퍼에 복사될 때까지만 차단합니다. 즉, 일부 수신자가 검색할 때까지 기다립니다. 값입니다."

간단히 말하면:

  1. 버퍼되지 않은 채널은 영구적으로 간주됩니다. full.
  2. 버퍼되지 않은 채널로 데이터를 보내면 다른 고루틴이 값을 검색할 때까지 발신자가 차단됩니다.

교착 상태 시나리오

제공된 코드 조각, 채널이 버퍼링되지 않았고 다른 작업이 없기 때문에 작업 c

교착 상태 해제

교착 상태를 해결하려면 다음 중 하나를 수행할 수 있습니다.

  1. 버퍼링된 채널: 버퍼링된 채널 생성(예: c := make(chan) int, 1)), 수신자가 준비되기 전에 송신자 고루틴이 일시적으로 값을 배치할 수 있는 작은 버퍼를 할당합니다.

OR

  1. 수신 고루틴을 소개합니다. : 채널로부터의 데이터 수신을 처리하기 위해 별도의 고루틴을 도입할 수 있습니다. 이렇게 하면 소비자가 항상 전송된 값을 검색할 수 있습니다.

수신 고루틴의 예:

package main

import "fmt"

func main() {
    c := make(chan int)    
    go func() {
        fmt.Println("received:", <-c)
    }()
    c <- 1   
}

여기서 go로 생성된 고루틴은 func() {...}는 채널에서 값을 수신하기 위해 지속적으로 기다립니다. 이 수신 고루틴을 도입하면 교착 상태가 방지됩니다.

결론적으로 전용 수신 메커니즘 없이 동일한 고루틴에서 버퍼링되지 않은 채널을 사용하면 교착 상태가 발생할 수 있습니다. 이를 방지하려면 버퍼링된 채널을 사용하거나 별도의 수신 고루틴을 도입하여 동시 고루틴 간의 적절한 데이터 전송을 보장하는 것이 좋습니다.

위 내용은 Go에서 버퍼링되지 않은 채널이 교착 상태를 일으키는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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