ホームページ >バックエンド開発 >Golang >チャネルを設定する関数呼び出しがゴルーチンに埋め込まれていない場合にデッドロックが発生するのはなぜですか?

チャネルを設定する関数呼び出しがゴルーチンに埋め込まれていない場合にデッドロックが発生するのはなぜですか?

王林
王林転載
2024-02-10 12:00:10763ブラウズ

当填充通道的函数调用未嵌入 Goroutine 中时,为什么会出现死锁?

チャネルを満たす関数呼び出しが Goroutine に埋め込まれていない場合、デッドロックが発生する理由は、チャネルの送受信操作がブロックされるためです。チャネルを埋める関数がメイン ゴルーチンで呼び出され、その埋め込み操作が関数内で実行する新しいゴルーチンに組み込まれていない場合、メイン ゴルーチンはチャネルにデータを受信するのに十分なスペースが確保されるまで待機します。充填動作が実行できなくなり、デッドロックにつながります。したがって、デッドロックを回避するには、チャネルの充填操作で同時実行用の Goroutine を使用し、充填操作と受信操作を同時に実行できるようにする必要があります。

質問の内容

sync パッケージとその waitgroup オプションについては知っていますが、このテストでは使用したくありません。 。セマフォをテストしています。

###ので、私は持っています: ### リーリー

私がテストしたいことは非常に単純です。

createjobs

関数があり、その唯一の目的は要素をチャネル (この場合は int チャネル) に追加することです。次に、そのチャネルからオブジェクトをプルし、次の要素をフェッチする前に 2 秒間スリープする worker を用意します。 今度は同期機能もあります。この関数の唯一の目的は、

worker

の実行時に開始されるプロセスをシミュレートすることです。このプロセスがアクティブな場合、sync が終了すると jobs 要素の処理を停止する必要があります。そのため、2 つのチャネルがあり、1 つはプロセスの開始を意味し、もう 1 つはプロセスの終了を意味します。 コードを実行すると次のエラーが発生します:

リーリー

createjobs

の呼び出し方法を変更する場合は、次のように goroutine でラップします。 リーリー

これで、コードは正しく実行されます。 なぜこれが起こっているのかを理解したいだけです。私が言いたいのは、

main

ルーチンが実行中で、

createjobs

(改行なし) を呼び出すため、この呼び出しが終了するまで main ルーチンをブロックする必要があるということです。 createjobs が終了すると、チャネル内に要素が追加されます。 main は実行を継続し、他のゴルーチン workersync を開始して作業を完了します。 main が終了する前に、スリーパーを追加して、以前に作成した goroutine が完了するまでの時間を与えます。 私はこの問題に対する他の解決策を求めているのではなく、createjobs が goroutine の外で発生したときに何が起こるかを知りたいだけです。

回避策

jobs

をバッファなしチャネルとして宣言し、20 個の値を同期的にプッシュしようとします。これにより、

createjobs(jobs)

を呼び出すときに main 関数がブロックされます。 13行目を次のように変更します: リーリー ...デッドロックを解決します。

編集 - コメントで説明を求められます:

バッファリングされていないチャネルには容量がなく、コンシューマがメッセージを受信するまでプロデューサの実行がブロックされます。 バッファなしチャネルをパイプに例えると、この場合のプロセスは次のようになります:

リーリー

createjobs(jobs)

が同期的に呼び出され、コンシューマーがまだ実行されていないために、デッドロックが発生します。

基本的にチャネルへの挿入とチャネルからの読み取りは並行して行われるため、関数 (

プロデューサー) がゴルーチンで呼び出されたときに機能しますか? ###はい。プロデューサが非同期で呼び出された場合、

main()

関数はブロックされないため、コンシューマも呼び出される可能性があります。この場合、ワーカーがタスクを 1 つずつ消費するのと同じように、プロデューサーはすべてのタスクを 1 つずつプッシュします。

以上がチャネルを設定する関数呼び出しがゴルーチンに埋め込まれていない場合にデッドロックが発生するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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