Heim  >  Artikel  >  Backend-Entwicklung  >  Wie schließe ich einen mit mehreren Goroutinen gefüllten Kanal, wenn alle Arbeiten erledigt sind?

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

WBOY
WBOYnach vorne
2024-02-10 12:27:10791Durchsuche

当所有工作完成后,如何关闭由多个 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
    }

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)
}()

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!

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