0

私のコードには、3つの同時ルーチンがあります。私は自分のコードの概要を簡単に説明しようとしていますが、

Routine 1 {
do something

*Send int to Routine 2
Send int to Routine 3
Print Something
Print Something*

do something
}

Routine 2 {
do something

*Send int to Routine 1
Send int to Routine 3
Print Something
Print Something*

do something
}

Routine 3 {
do something

*Send int to Routine 1
Send int to Routine 2
Print Something
Print Something*

do something
}

main {
routine1
routine2
routine3
}

2つの間のコード(2つのスターマーク間のコード)が実行されている間、制御のフローは他のgoルーチンに移動してはなりません。たとえば、routine1が2つのスター間のイベント(送信イベントと印刷イベント)を実行している場合、ルーチン2と3をブロックする必要があります(つまり、実行フローはルーチン1からルーチン2または3に渡されません)。最後の印刷イベントが完了した後、実行の流れはルーチン2または3に渡される可能性があります。誰かが指定することで私を助けてくれますか、どうすればこれを達成できますか?WaitGroupで上記の仕様を実装することは可能ですか?WaitGroupを使用して上記の例を実装する簡単な例を挙げて、誰かに教えてもらえますか。ありがとう。

NB:これはこれの繰り返しの質問かもしれませ。そのsync-lockメカニズムを使用して試しましたが、コードが大きいためにlock-unlockを適切に設定できず、デッドロック状態が発生している可能性があります(または私の方法エラーが発生している可能性があります)。誰かが簡単な手順で私を助けてくれるので、私はこれを達成することができます。ここに私のコードの簡単な例を示します。ここでは、2つのプリントを配置し、ミューテックス内にイベントを送信します(ルーチン1の場合)。したがって、ルーチン2はそれを中断できません。どうすればそれが可能か教えてくれませんか。与えられた1つの可能な解決策、 エラーを与えるhttp://play.golang.org/p/-uoQSqBJKS 。

4

2 に答える 2

3

なぜあなたはこれをしたいのですか?

デッドロックの問題は、他のゴルーチンのスケジュールを許可しない場合、バッファリングがない限り、チャネル送信を続行できないことです。Goのチャネルには有限のバッファリングがあるため、いっぱいになっている間に送信される前に、ドレインの競合状態になります。無限のバッファリングを導入することも、各送信を独自のゴルーチンに入れることもできますが、それは次のようになります。なぜこれを行おうとしているのか。何を達成しようとしていますか?

もう1つのこと:* sの間の3セットのコードの相互排除のみを保証したい場合は、そうです、ミューテックスを使用できます。ブロックが中断された場所に関係なく、ブロックを中断するコードがないことを確認する場合は、runtime.LockOSThreadおよびruntime.UnlockOSThreadを使用する必要があります。これらはかなり低レベルであり、何をしているのかを知る必要があり、必要になることはめったにありません。他のゴルーチンを実行しないようにする場合は、runtime.GOMAXPROCS(1)が必要です。これは現在デフォルトです。

于 2011-12-04T05:25:26.107 に答える
3

あなたの質問に答える際の問題は、あなたの問題が実際に何であるかを誰も理解していないように見えることです。進展はありませんが、ほぼ同じことについて繰り返し質問されているようです。これを言っても違和感はありません。それは、他の人が理解できる方法であなたの問題を再定式化する提案によってあなたを助ける試みです。考えられる素晴らしい副作用として、いくつかの問題は、理解できる方法で他の人に説明されている間、それ自体で解決します。私はそれを自分で何度も経験しました。

もう1つのヒントは、明示的な同期とチャネル通信の疑わしい組み合わせにある可能性があります。それは必ずしもデザインが壊れているという意味ではありません。それは典型的な/単純なケースでは起こりません。繰り返しになりますが、あなたの問題は非定型/些細なことではないかもしれません。

おそらく、チャネルのみを使用して問題を再設計することは、どういうわけか可能です。実際、(Goでの)明示的な同期に関連するすべての問題は、チャネルのみを使用してコーディングできると思います。とは言うものの、いくつかの問題は明示的な同期で非常に簡単に記述されることは事実です。また、チャネル通信は、それ自体が安価ですが、ほとんどの同期プリミティブほど安価ではありません。しかし、それは後でコードが機能するときに世話をすることができます。一部の人の「パターン」がsync.Mutexをコードに目に見える形で現れる場合は、コードに切り替えることが可能であり、コードがすでに機能していて、調整中にステップを監視するテストがある場合は、はるかに簡単に切り替えることができます。 。

独立して行動するエージェントのようなあなたのゴルーチンについて考えてみてください:

  • チャネルから受信したデータを独占的に所有します。言語はこれを強制しません、あなたは自分の規律を展開しなければなりません。
  • チャンネルに送信したデータにはもう触れないでください。それは最初のルールに従いますが、明確にするのに十分重要です。
  • ワークフロー/計算のユニット全体をカプセル化するデータ型によって他のエージェント(ゴルーチン)と対話します。これにより、たとえば、「ユニット」が完了する前に適切な数のチャネルメッセージを取得するという以前の苦労がなくなります。
  • 使用するすべてのチャネルについて、チャネルをバッファリング解除する必要があるのか​​、固定数のアイテムに対してバッファリングする必要があるのか​​、またはバインド解除できるのかを事前に完全に明確にする必要があります。
  • エージェントが独自のタスクを実行するために必要な場合は、他のエージェントからメッセージを受け取ることよりも、他のエージェントが何をしているのかを考える(知る)必要はありません。全体像の一部です。

このような少数のルールを使用するだけでも、推論がより簡単で、通常は他の同期を必要としないコードが生成されるはずです。(現在、ミッションクリティカルなアプリケーションのパフォーマンスの問題を意図的に無視しています。)

于 2011-12-04T10:45:10.913 に答える