2016-06-29 33 views
5

Stellen Sie sich den folgenden Code ein:Sind goroutines Müll zusammen mit ihren Kanälen gesammelt?

func waitForOneOfTwoProcesses() { 

    c := make(chan bool) 
    go func() { 
     time.Sleep(1 * time.Second) 
     c<-true 
    }() 
    go func() { 
     time.Sleep(2 * time.Second) 
     c<-true 
    }() 
    <-c 

} 

dies einen Kanal und einen goroutine austritt oder erkennen, geht das c und die goroutine verlassen kann weg ist?

Wäre die Antwort anders, wenn der Kanal eine Puffergröße von 2 hat?

Antwort

3

Wenn der Kanal ungepuffert ist, wird eine der anonymen Funktionen nicht zurückgegeben. Das Programm leckt eine Goroutine und einen Kanal.

Wenn der Kanal eine Puffergröße größer oder gleich eins hat, werden beide anonyme Funktionen zurückgegeben. Die von den Goroutinen und dem Kanal verwendeten Ressourcen werden zurückgewonnen.

Eine Puffergröße von 1 ist ausreichend, um das Leck zu verhindern. Die Funktion waitForOneOfTwoProcesses empfängt einen der an c gesendeten Werte. Der zweite Wert, der an c gesendet wird, wird im Kanal gepuffert (der vom GC erfasst wird).

Eine andere Möglichkeit, sicherzustellen, dass die Goroutinen zurückkehren, besteht darin, nicht blockierende Nachrichten zu verwenden. Ersetzen Sie die c <- true Linien mit:

select { 
case c <- true: 
default: 
} 
+0

Also das Schreiben in die Kanalblöcke, obwohl der Kanal außerhalb des Gültigkeitsbereichs und kann nie wieder gelesen werden. Ich frage mich, ob das ein Fehler oder eine Funktion ist. – AndreKR

+0

Ja, Senden wird blockiert, obwohl kein Empfänger vorhanden ist. Die Laufzeitumgebung könnte so geschrieben werden, dass sie erkennt, wenn die Anwendung in diesem speziellen Beispiel den Empfang auf einem Kanal beendet hat. Die Laufzeitumgebung kann diese Laufzeitumgebung jedoch nicht erkennen. –

+1

Als Hinweis, gibt es auch eine "non-blocking send", die genau dieses Problem löst - Sie würden den Puffer auf den Kanal auf 1 setzen und jeder würde ohne zu blockieren senden. Ausführlich beschrieben hier: https://blog.golang.org/go-concurrency-patterns-timing-out-and –