Heim  >  Artikel  >  Backend-Entwicklung  >  Schreiben Sie Chan in die sync.WaitGroup-Goroutine

Schreiben Sie Chan in die sync.WaitGroup-Goroutine

PHPz
PHPznach vorne
2024-02-09 17:00:10646Durchsuche

在sync.WaitGroup goroutine中写入chan

Der PHP-Editor Yuzi wird eine Methode zum Schreiben von Chan in der sync.WaitGroup-Goroutine vorstellen. Bei der gleichzeitigen Programmierung ist sync.WaitGroup ein sehr nützlicher Synchronisationsmechanismus, der auf den Abschluss der Ausführung einer Gruppe von Goroutinen warten kann. Manchmal müssen wir jedoch die Ergebnisse in einen Kanal schreiben, nachdem die Goroutine die Ausführung abgeschlossen hat, damit sie von anderen Goroutinen genutzt werden können. In diesem Artikel wird detailliert beschrieben, wie diese Funktion in der sync.WaitGroup-Goroutine implementiert wird. Werfen wir einen Blick darauf!

Frageninhalt

Ich erhalte eine Liste mit Elementen von einem API-Endpunkt. Dann stelle ich für jedes Projekt eine weitere API-Anfrage, um Daten über das einzelne Projekt zu erhalten.

Ich kann nicht gleichzeitig eine zweite API-Anfrage an jedes Projekt stellen, da die Rate meines API-Tokens begrenzt ist und ich gedrosselt werde, wenn ich zu viele Anfragen gleichzeitig stelle.

Allerdings können die anfänglichen API-Antwortdaten in mehrere Seiten aufgeteilt werden, sodass ich Seiten mit Daten gleichzeitig verarbeiten kann.

Nach einiger Recherche macht der folgende Code genau das, was ich will:

func main() {
    // pretend paginated results from initial API request
    page1 := []int{1, 2, 3}
    page2 := []int{4, 5, 6}
    page3 := []int{7, 8, 9}
    pages := [][]int{page1, page2, page3}

    results := make(chan string)

    var wg sync.WaitGroup
    for i := range pages {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            for j := range pages[i] {
                // simulate making additional API request and building the report
                time.Sleep(500 * time.Millisecond)

                result := fmt.Sprintf("Finished creating report for %d", pages[i][j])
                results <- result
            }

        }(i)
    }

    go func() {
        wg.Wait()
        close(results)
    }()

    for result := range results {
        fmt.Println(result)
    }
}

Ich möchte verstehen, warum es funktioniert:

go func() {
    wg.Wait()
    close(results)
}()

Mein erster Versuch war erfolglos – ich dachte, ich könnte das Ergebnis beim wg.Wait() 之后遍历通道,并且我会在结果写入 resultsChannelieren ablesen.

func main() {
    // pretend paginated results from initial API request
    page1 := []int{1, 2, 3}
    page2 := []int{4, 5, 6}
    page3 := []int{7, 8, 9}
    pages := [][]int{page1, page2, page3}

    results := make(chan string)

    var wg sync.WaitGroup
    for i := range pages {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            for j := range pages[i] {
                // simulate making additional API request and building the report
                time.Sleep(500 * time.Millisecond)

                result := fmt.Sprintf("Finished creating report for %d", pages[i][j])
                results <- result
            }

        }(i)
    }

    // does not work
    wg.Wait()
    close(results)

    for result := range results {
        fmt.Println(result)
    }
}

Lösung

Beim ersten Versuch:

  1. Die Haupt-Goroutine veranlasst 3 Goroutinen, Werte in den Ergebniskanal einzugeben.
  2. Die Haupt-Coroutine wartet auf den Abschluss aller Coroutinen.
  3. Eine der Goroutinen gibt einen Wert in den Ergebniskanal ein und füllt den Kanal (Kanalgröße beträgt 1 String).
  4. Jetzt können alle drei Goroutinen keine Werte mehr in den Ergebniskanal einfügen und gehen in den Ruhezustand, bis der Ergebniskanal freigegeben wird.
  5. Alle Goroutinen befinden sich im Ruhezustand. Du steckst in einer Sackgasse.

Beim zweiten Versuch:

  1. Die Haupt-Goroutine enthält 4 Goroutinen.
  2. 3 Goroutinen zum Einfügen von Werten in Ergebniskanäle.
  3. Die andere Goroutine (ich nenne sie die vierte) wartet darauf, dass diese 3 Goroutinen fertig sind.
  4. Gleichzeitig wartet die Haupt-Coroutine auf den Wert im Ergebniskanal (for-Schleife)
  5. Wenn in diesem Fall eine der Goroutinen einen Wert in den Ergebniskanal einfügt, blockiert sie die verbleibenden drei Goroutinen; die Haupt-Goroutine entnimmt den Wert aus dem Ergebniskanal und gibt so die Blockierung der anderen Goroutinen frei.
  6. Also setzen alle 3 Goroutinen ihre jeweiligen Werte und enden
  7. Dann schließt die vierte Goroutine den Kanal
  8. Die Haupt-Goroutine beendet ihre for-Schleife.

Das obige ist der detaillierte Inhalt vonSchreiben Sie Chan in die sync.WaitGroup-Goroutine. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen