2016-06-29 14 views
5

Immaginate il seguente codice:I rifiuti goroutini vengono raccolti insieme ai loro canali?

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 

} 

Fa questa perdita di un canale e un goroutine o fa andare riconoscono che c non c'è più e il goroutine può uscire?

La risposta è diversa se il canale ha una dimensione del buffer pari a 2?

risposta

3

Se il canale non è bloccato, una delle funzioni anonime non verrà restituita. Il programma perde una goroutine e un canale.

Se il canale ha una dimensione del buffer maggiore o uguale a uno, verranno restituite entrambe le funzioni anonime. Le risorse utilizzate dalle goroutine e dal canale saranno recuperate.

Una dimensione del buffer di uno è sufficiente per impedire la perdita. La funzione waitForOneOfTwoProcesses riceve uno dei valori inviati a c. Il secondo valore inviato a c viene memorizzato nel canale (che viene raccolto dal GC).

Un altro modo per garantire il ritorno delle goroutine è utilizzare l'invio non bloccante. Sostituire le linee c <- true con:

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

Così la scrittura per i blocchi di canale, anche se il canale è fuori portata e non può mai essere letto da ancora. Mi chiedo se sia un bug o una funzionalità. – AndreKR

+0

Sì, l'invio verrà bloccato anche se non è presente un ricevitore. Il runtime può essere scritto per rilevare quando l'applicazione viene eseguita ricevendo su un canale in questo specifico esempio, ma non è qualcosa che il runtime può rilevare in generale. –

+1

Come nota, è disponibile anche una "non-blocking send", che risolve questo problema esatto - avresti impostato il buffer sul canale su 1 e ognuno avrebbe inviato senza bloccare. Descritto più dettagliatamente qui: https://blog.golang.org/go-concurrency-patterns-timing-out-and –

Problemi correlati