Go ルーチンを正常に停止する方法
Go では、ゴルーチンは軽量の同時実行性を提供しますが、それらを正常に終了するのは難しい場合があります。この質問は、ゴルーチンの実行を停止するためにシグナルをゴルーチンに送信する必要性について説明します。
提供されたコードは、ブール フラグ (tooLate) を true に設定してゴルーチンを停止する試みを示しています。ただし、チャネルからの読み取りがゴルーチンをブロックするため、このアプローチには問題があります。
解決策 1: 追加のチャネルを使用する
この解決策には 2 番目のチャネルの使用が含まれます (遅すぎる)停止信号を伝達します。このチャネルは、ゴルーチンが積極的に読み取っていないときでも開いたままになります。
<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>
このアプローチでは、ゴルーチンは cond.Signal() からシグナルを受信するまで cond.Wait() メソッドで待機します。
以上がGo ルーチンを正常に停止する方法: デッドロックや応答しないプロセスを回避するためのガイド?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。