0

https://golang.org/doc/codewalk/sharemem/のコードを理解しようとしてい ます が、チャネルを介してリソースを渡すことについてはほとんどの部分を理解していますが、プログラムが実行される無限ループを理解することはできません. ポーラー関数 (メイン関数から受信する) の "in" チャネルが 3 つのポーラー go ルーチンしか実行しない場合、プログラムはどのようにポーラー関数を無限に実行しますか?

StateMonitor が無限ループを伴う匿名の go 関数を持っているという考えが浮かびました。ただし、Poller 関数から受信しないと LogState を更新できません。私は、プログラムが URL への Get 要求を無限に実行すると想定しています。

私が理解したことが間違っていないことを確認するために、wifi のオンとオフを切り替えてプログラムをテストし、ログが変更されるかどうかを確認しました。驚いたことに、数回繰り返しますが、その後、変更への応答を停止し、同じログを表示し続けます。それで、それはプログラムにバグがあるということですか?それとも、いくつかの基本的な概念を理解していないということですか?

4

3 に答える 3

0

ポーラー関数(メイン関数から受信する)の「in」チャネルが3つのポーラーgoルーチンのみを実行する場合、プログラムはどのようにポーラー関数を無限に実行しますか?

したがって、最初にプログラムは 2 つのポーラーを作成します。

for i := 0; i < numPollers; i++ {
    go Poller(pending, complete, status)
}

次に、3 つのリソースを保留に送信します。

for _, url := range urls {
    pending <- &Resource{url: url}
}

すべてのポーラーは保留中から読み取り、リソースをポーリングします。

for r := range in {
    s := r.Poll()
    status <- State{r.url, s}
    out <- r
}

このコードは無限に実行されるように見えますが、通常、キューからの読み取りをブロックしています。したがって、このループは次の値が表示されるのを待ちます。

実際にそれを乗り越えてみましょう:

  1. リソースを読み取る 2 つのポーラーがあります。
  2. プログラムは最初のリソースをキューに送信します。
  3. ポーラーの 1 つがリソースを取得し、プールを開始します。もう一人は待っています。
  4. ある時点で、プログラムは新しいリソースをキューに送信します。
  5. 最初のポーラーがビジーであるため、2 番目のポーラーはブロックが解除され、ポーリングを開始します。
  6. プログラムは 3 番目のリソースを送信し、2 つのポーラーがビジーであるためブロックします。
  7. ポーラーの 1 つが完了すると、最後のリソースを取得して続行します。
  8. その間に、メイン プログラムは完全なキューから値を読み取ります。

for r := range in { s := r.Poll() status <- State{r.url, s} out <- r }このコードはどのように無限に実行されますか? 「in」チャネルをループし、「in」が保留中のキューからリソースを取得する場合、数回の反復後に終了する必要があります。これはまさに私が理解していない部分だと思います。

正確には、キューinからリソースを取得しません。キューですキュー (または私が同じ意味で使用するチャネル) は、closeを呼び出すことで閉じることができますが、明示的に閉じられない限り、生きていると見なされます。それからの読み取りは、次の値が与えられるまで現在のゴルーチンをブロックします。そしてゴロチン再開。pendingin pending

チャンネルというと要素数が固定された配列のようなものだと思い込んでいると思います。ではない。要素の数が無限であるが、例外をスローする可能性のある読み取りをブロックする配列が好きであると考えてください (概念に慣れていない場合は、キューを閉じることの大まかな近似です)。

于 2015-08-07T11:29:18.000 に答える
0

チャネルでの送信操作は、受信者が同じチャネルで使用できるようになるまでブロックされます。チャネルに値の受信者がいない場合、他の値をチャネルに入れることはできません。逆に、チャネルが空でない場合、チャネルで新しい値を送信することはできません! したがって、送信操作は、チャネルが再び使用可能になるまで待機します。

一方、チャネルの受信操作は、送信者が同じチャネルで使用できるようになるまでブロックされます。チャネルに値がない場合、受信者はブロックされます。

チャネルのブロックを解除するには、無限ループでチャネルからデータをプルする必要があります。

これが、プログラムが無限ループでデータを送受信している理由の説明です。

于 2015-08-07T11:29:48.700 に答える
-1

これは私を明確にします。スリープ機能は実際に無限ループを引き起こします。

https://groups.google.com/forum/#!searchin/golang-nuts/sunil/golang-nuts/FSx8GmoRaNM/Nz9CdSF_zh8J][1]

于 2015-08-11T11:54:47.883 に答える