Go ルーチンを正常に停止する方法: デッドロックや応答しないプロセスを回避するためのガイド?

Linda Hamilton
リリース: 2024-10-28 14:11:02
オリジナル
535 人が閲覧しました

 How to Gracefully Stop a Go Routine: A Guide to Avoiding Deadlocks and Unresponsive Processes?

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 サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!