Go 루틴을 우아하게 중지하는 방법
Go에서 고루틴은 가벼운 동시성을 제공하지만 우아하게 종료하는 것은 어려울 수 있습니다. 이 질문은 고루틴의 실행을 중지하기 위해 신호를 보내야 하는 필요성에 대해 설명합니다.
제공된 코드는 부울 플래그(tooLate)를 true로 설정하여 고루틴을 중지하려는 시도를 보여줍니다. 그러나 이 접근 방식은 채널에서 읽는 것이 고루틴을 차단하므로 문제가 있습니다.
해결책 1: 추가 채널 사용
해결책에는 두 번째 채널을 사용하는 것이 포함됩니다(너무 늦음). 정지 신호를 전달합니다. 이 채널은 고루틴이 적극적으로 읽지 않을 때에도 열려 있습니다.
<code class="go">func main() { tooLate := make(chan struct{}) // Unbuffered channel for stop signal proCh := make(chan string) go func() { for { fmt.Println("working") time.Sleep(1 * time.Second) select { case <-tooLate: fmt.Println("stopped") return case proCh <- "processed": // Non-blocking send default: // Allows the goroutine to continue without blocking } fmt.Println("done here") } }() select { case proc := <-proCh: fmt.Println(proc) case <-time.After(1 * time.Second): fmt.Println("too late") close(tooLate) // Signal to goroutine to stop } time.Sleep(4 * time.Second) fmt.Println("finish\n") }</code>
이 솔루션에서는 시간 제한이 만료되면 tooLate 채널이 닫혀서 고루틴이 차단 select 문을 종료하게 됩니다.
해결책 2: sync.Cond 사용
또는 sync.Cond 유형을 사용하여 보다 정교한 신호 메커니즘을 구현할 수 있습니다. 예는 다음과 같습니다.
<code class="go">func main() { var stopped bool cond := sync.NewCond(new(sync.Mutex)) go func() { for { cond.L.Lock() defer cond.L.Unlock() if stopped { fmt.Println("stopped") return } fmt.Println("working") cond.Wait() // Wait for the signal to stop } }() time.Sleep(1 * time.Second) cond.Signal() // Send the stop signal time.Sleep(4 * time.Second) fmt.Println("finish\n") }</code>
이 접근 방식을 사용하면 goroutine은 cond.Signal()에서 신호를 받을 때까지 cond.Wait() 메서드를 기다립니다.
위 내용은 Go 루틴을 적절하게 중지하는 방법: 교착 상태 및 응답하지 않는 프로세스를 방지하기 위한 가이드?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!