Wie schließe ich einen mit mehreren Goroutinen gefüllten Kanal, wenn alle Arbeiten erledigt sind?

WBOY
Freigeben: 2024-02-10 12:27:10
nach vorne
825 Leute haben es durchsucht

当所有工作完成后,如何关闭由多个 goroutine 填充的通道?

Wie man einen mit mehreren Goroutinen gefüllten Kanal schließt, wenn alle Arbeiten abgeschlossen sind, ist eine häufig gestellte Frage. In Go ist das Schließen eines Kanals eine Möglichkeit, dem Empfänger mitzuteilen, dass keine Daten mehr vorhanden sind. Durch das Schließen des Kanals kann der Empfänger rechtzeitig erkennen, dass der Sender alle Sendevorgänge abgeschlossen hat. In einem Kanal mit mehreren Goroutinen können wir einen Zähler verwenden, um zu verfolgen, wie viele weitere Goroutinen Daten an den Kanal senden. Wenn der Zähler auf 0 fällt, sind alle Arbeiten abgeschlossen und wir können den Kanal sicher schließen. Nach dem Schließen des Kanals kann der Empfänger mithilfe zusätzlicher Variablen im Empfangsausdruck feststellen, ob der Kanal geschlossen wurde. Auf diese Weise können wir sicherstellen, dass von mehreren Goroutinen gefüllte Kanäle nach Abschluss aller Arbeiten ordnungsgemäß geschlossen werden, wodurch Ressourcenlecks und Deadlock-Probleme vermieden werden.

Frageninhalt

Ich versuche, dem Go-Weg zu folgen, „nicht über den gemeinsamen Speicher zu kommunizieren, sondern den Speicher durch Kommunikation zu teilen“ und Kanäle zu verwenden, um zu erledigende Aufgaben asynchron zu kommunizieren und die Ergebnisse der Verarbeitungsaufgaben zurückzusenden.

Der Einfachheit halber habe ich die Kanaltypen in int anstelle ihrer tatsächlichen Strukturen geändert. Und lange Bearbeitung durch time.Sleep() ersetzt.

Wie schließe ich ProducedResults ,以便此代码不会卡在最后一个 for, nachdem alle Aufgabenergebnisse zurückgesendet wurden?

quantityOfTasks:= 100
    quantityOfWorkers:= 60
    remainingTasks := make(chan int)
    producedResults := make(chan int)

    // produce tasks
    go func() {
        for i := 0; i < quantityOfTasks; i++ {
            remainingTasks <- 1
        }
        close(remainingTasks)
    }()

    // produce workers
    for i := 0; i < quantityOfWorkers; i++ {
        go func() {
            for taskSize := range remainingTasks {
                // simulate a long task
                time.Sleep(time.Second * time.Duration(taskSize))
                // return the result of the long task
                producedResults <- taskSize
            }
        }()
    }

    // read the results of the tasks and agregate them
    executedTasks := 0
    for resultOfTheTask := range producedResults { //this loop will never finish because producedResults never gets closed
        // consolidate the results of the tasks
        executedTasks += resultOfTheTask
    }
Nach dem Login kopieren

Workaround

Sie möchten den Kanal schließen, nachdem alle Goroutinen, die darauf schreiben, zurückgekehrt sind. Mit WaitGroup können Sie Folgendes erreichen:

wg:=sync.WaitGroup{}

for i := 0; i < quantityOfWorkers; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            for taskSize := range remainingTasks {
                //simulate a long task
                time.Sleep(time.Second * time.Duration(taskSize))
                //return the result of the long task
                producedResults <- taskSize
            }
        }()
}

go func() {
  wg.Wait()
  close(producedResults)
}()
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonWie schließe ich einen mit mehreren Goroutinen gefüllten Kanal, wenn alle Arbeiten erledigt sind?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage