2016-06-29 11 views
5

Wyobraźmy sobie następujący kod:Czy zebrane śmieci są zbierane razem z kanałami?

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 

} 

Czy ten wyciek kanał i goroutine lub wykracza uznają, że c zniknął i goroutine może wyjść?

Czy odpowiedź byłaby inna, gdyby kanał miał rozmiar bufora 2?

Odpowiedz

3

Jeśli kanał jest niebuforowany, to jedna z anonimowych funkcji nie zostanie zwrócona. Program przecieka goroutine i kanał.

Jeśli kanał ma rozmiar bufora większy lub równy jeden, to obie funkcje anonimowe powrócą. Zasoby wykorzystywane przez goroutiny i kanał zostaną odzyskane.

Wielkość bufora jednego jest wystarczająca, aby zapobiec wyciekowi. Funkcja waitForOneOfTwoProcesses odbiera jedną z wartości przesłanych do c. Druga wartość wysłana do c jest buforowana w kanale (który jest gromadzony przez GC).

Innym sposobem na powrót nawrotów jest użycie wysyłania bez blokowania. Zastąp linie c <- true za pomocą:

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

Tak więc zapis do bloków kanałów, nawet jeśli kanał jest poza zakresem i nie można go odczytać od nowa. Zastanawiam się, czy to błąd czy funkcja. – AndreKR

+0

Tak, wysyłanie zostanie zablokowane, nawet jeśli nie ma odbiornika. Środowisko wykonawcze można zapisać, aby wykryć, kiedy aplikacja odbierze kanał w tym konkretnym przykładzie, ale nie jest to coś, co środowisko wykonawcze może wykryć w ogóle. –

+1

Jako uwaga, dostępny jest również "blokujący wysyłanie", który rozwiązuje ten dokładny problem - ustawiasz bufor na kanale na 1, a każdy będzie wysyłać bez blokowania. Opisano bardziej szczegółowo tutaj: https://blog.golang.org/go-concurrency-patterns-timing-out-and –

Powiązane problemy