고루틴에서 버퍼링되지 않은 채널의 교착 상태
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의 공식 문서에 설명된 대로 "만약 채널이 버퍼링되지 않은 경우 송신자는 수신자가 값을 수신할 때까지 차단합니다. 채널에 버퍼가 있으면 송신자는 값이 버퍼에 복사될 때까지만 차단합니다. 즉, 일부 수신자가 검색할 때까지 기다립니다. 값입니다."
간단히 말하면:
교착 상태 시나리오
제공된 코드 조각, 채널이 버퍼링되지 않았고 다른 작업이 없기 때문에 작업 c
교착 상태 해제
교착 상태를 해결하려면 다음 중 하나를 수행할 수 있습니다.
OR
수신 고루틴의 예:
package main import "fmt" func main() { c := make(chan int) go func() { fmt.Println("received:", <-c) }() c <- 1 }
여기서 go로 생성된 고루틴은 func() {...}는 채널에서 값을 수신하기 위해 지속적으로 기다립니다. 이 수신 고루틴을 도입하면 교착 상태가 방지됩니다.
결론적으로 전용 수신 메커니즘 없이 동일한 고루틴에서 버퍼링되지 않은 채널을 사용하면 교착 상태가 발생할 수 있습니다. 이를 방지하려면 버퍼링된 채널을 사용하거나 별도의 수신 고루틴을 도입하여 동시 고루틴 간의 적절한 데이터 전송을 보장하는 것이 좋습니다.
위 내용은 Go에서 버퍼링되지 않은 채널이 교착 상태를 일으키는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!