ホームページ  >  記事  >  バックエンド開発  >  goroutine の作業が完了する前に Go プログラムが終了する

goroutine の作業が完了する前に Go プログラムが終了する

PHPz
PHPz転載
2024-02-08 22:57:20880ブラウズ

Go 程序在 goroutine 工作完成之前退出

この記事では、php エディターの Xiaoxin が、Go プログラムに関する重要な問題、つまり goroutine の作業が完了する前に終了する状況について紹介します。 Go 言語では、ゴルーチンはタスクを同時に実行できる軽量のスレッドです。ただし、ゴルーチンの作業が完了する前にプログラムが終了する可能性がある場合、プログラムがタスクを正しく完了できるように、この状況を処理する方法を理解する必要があります。次のコンテンツでは、この問題を調査し、それを解決するためのいくつかのソリューションを提供します。

質問の内容

チャンネルを適切にブロックして閉じる方法がわかりません。任意の数のワーカーを開始しているのですが、メイン関数がワーカーが完了する前に終了するか、チャネルが閉じられていないためにハングすることがわかりました。ワーカーがメイン チャネルを終了せずにチャネルを読み取るのを停止し、終了したら正常にチャネルを閉じてループを終了する、より良い方法が必要です。私が試みてもデッドロックに終わります。

待機グループの使用など、いくつかのことを試しましたが、問題は解決しません。 time.sleep を追加するとプログラムは期待どおりに動作しますが、コメントアウトすると何も行われないことに気付きました。

リーリー

これは、sleep を保持する実行可能なサンプル https://go.dev/play/p/qhqnj-ajqbi です。これは、スリープ タイムアウトがコメント化された壊れたコードです。

リーリー

また、defer wg.done()worker() 関数内に移動しようとしましたが、同じ問題であり、スリープなしでは機能しません。

リーリー

私は間違ったパラダイムを選択したのでしょうか、それとも単に間違ったパラダイムを使用しているだけなのでしょうか?

回避策

私は最初に「コードを機能させるためにコードを少し調整できますか? それともこの問題を再考する必要がありますか? 」と質問しました。その答えは次のとおりです。はい、小さな調整があることがわかりました。

チャネルに関する興味深い基本概念を学ぶ必要がありました。閉じたチャネルからデータを読み取ることができる、つまりチャネルをドレインすることができます。元の例で述べたように、チャンネルを閉じるのに適した場所が見つからないため、range は終了しません。また、他の創造的な方法で強制的にチャンネルを強制した場合でも、プログラムの動作が悪くなります。

    チャネル内のすべてのコンテンツを処理せずに終了しました
  • デッドロックまたは閉じたチャネルでの送信
これは、「

real」コードの微妙な違いによるもので、チャネル コンテンツ の処理に必要な時間は、# のデータを設定するのに必要な時間よりも長くなります。 ## チャンネルとモノが同期していません。 送信側でチャネルを閉じるための明確で実用的な方法がないため (チャネル チュートリアルの 99% で推奨されています)、複数のワーカーがチャネルを読んでいて、ワーカーがそのことを知らない場合、実際には最後の値が読み取られる main の goroutine を使用してこれを行うことは許容されます。

###解決###

ワーカーを独自の

sync.waitgroup

でラップし、

worker.wait()

を使用して プログラムの終了をブロックしました。送信するデータがなくなったら、チャネルを独立して close() します、つまり、ライターが独自の待機グループを使用して終了するのを待ってブロックします。範囲ループの終了ケースは、チャネルのデフォルト値が返されるとき、つまり、チャネルの終わりに到達したときに eof タイプに達すると終了するためです。ブロッキング ランデブー チャネルは、閉じられるまでエンドポイントを持ちません。 これに対する私の見解は、並列にプッシュされる値の数がわからない場合、バッファリングされていないチャネルはスコープ内にあるため、そのチャネルを閉じるまで go はそのチャネルの長さを知る方法がありません。 。 。閉じられているため、終了値または最後まで残っているものを読み取ることを意味します。 workers.wait() は完了するまでブロックされます。

解決された操作の例

https://www.php.cn/link/2bf0ccdbb4d3ebbcb990af74bd78c658 クローズドチャネルの読み取り例 https://www.php.cn/link/d5397f1497b5cdaad7253fdc92db610b

###出力### リーリー

以上がgoroutine の作業が完了する前に Go プログラムが終了するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はstackoverflow.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。