2014-07-23 18 views
6

Sto cercando di capire, come funziona il canale golang. Ho letto un libro sulla lingua go e ho trovato il seguente esempio.Perché succede qui un deadlock

package main 

import (
    "fmt" 
) 

// Send the sequence 2, 3, 4, ... to returned channel 
func generate() chan int { 
    ch := make(chan int) 
    go func() { 
     for i := 2; i <= 100 ; i++ { 
      ch <- i 
     } 
    }() 
    return ch 
} 

// Filter out input values divisible by 'prime', send rest to returned channel 
func filter(in chan int, prime int) chan int { 
    out := make(chan int) 
    go func() { 
     for { 
      if i := <-in; i%prime != 0 { 
       out <- i 
      } 
     } 
    }() 
    return out 
} 

func sieve() chan int { 
    out := make(chan int) 
    go func() { 
     ch := generate() 
     for { 
      prime := <-ch 
      ch = filter(ch, prime) 
      out <- prime 
     } 
    }() 
    return out 
} 

func main() { 
    primes := sieve() 
    for { 
     fmt.Println(<-primes) 
    } 
} 

Quando ho eseguito questo programma, ho una situazione di stallo, ma quando cambio la funzione di generare per

// Send the sequence 2, 3, 4, ... to returned channel 
func generate() chan int { 
    ch := make(chan int) 
    go func() { 
     for i := 2; ; i++ { 
      ch <- i 
     } 
    }() 
    return ch 
} 

Poi il programma verrà eseguito il ciclo infinito, ma non deadlock. Perché ottengo un deadlock quando rimuovo la condizione in loop?

risposta

9

Cosa intendi con principio di blocco?

si può vedere illustrato nel post del blog "The Nature Of Channels In Go"

per un buffer di canale:

http://3.bp.blogspot.com/-vnJIWvlbP-E/UwDVICJKB9I/AAAAAAAANX0/T04V_58i8Vs/s1600/Screen+Shot+2014-02-16+at+10.10.54+AM.png

(Illustrazione dal blog post "The Nature Of Channels In Go", scritto da William Kennedy, febbraio 2014)

I canali non bufferizzati non hanno capacità e pertanto richiedono che entrambe le goroutine siano pronte per effettuare qualsiasi scambio.
Quando una goroutine tenta di scrivere una risorsa su un canale non bufferizzato e non vi è alcuna goroutine in attesa di ricevere la risorsa, il canale bloccherà la goroutine e la attenderà.
Quando una goroutine tenta di leggere da un canale non bufferizzato e non vi è alcuna goroutine in attesa di inviare una risorsa, il canale bloccherà la goroutine e lo attenderà.

Questo è ciò che accade nel vostro caso con il tuo lettore:

func main() { 
    primes := sieve() 
    for { 
     fmt.Println(<-primes) 
    } 
} 

dal primes non è mai chiusa, main rimane bloccato.
It (main) è in fase 3:

al punto 3, il goroutine sulla destra mette la mano nel canale o esegue una lettura .
Tale goroutine è anche bloccata nel canale fino allo scambio completo.

Il mittente non chiama mai close(primes).

+0

Ho un deadlock, perché la goroutine nella funzione di generare è che il canale è chiuso dopo 100 cicli e primi ancora aspettano di ricevere i dati giusto? –

+0

@zero_coding non è chiuso: non vedo 'close (primi)' ovunque – VonC

+0

Intendo perché il ricevitore non si chiude, ma il mittente è chiuso a destra? Niente più mittente. –

5

Consideriamo un esempio più semplice:

func generate() chan int { 
    ch := make(chan int) 
    go func() { 
     for i := 2; /*i < 100*/; i++ { 
      ch <- i 
     } 
    }() 
    return ch 
} 

func main() { 
    for i := range generate() { 
     fmt.Println(i) 
    } 
} 

Con la condizione i < 100 senza commenti, il goroutine generato da generate fermate dopo l'invio di 98 numeri. Tuttavia, non chiude il canale, quindi main non ha modo di sapere che non verranno inviati altri numeri e continua a bloccare il canale. Dal momento che main è l'unica goroutine ancora esistente (l'altra è tornata) e sta bloccando, si ha una situazione di stallo.

+0

Ho letto anche l'argomento sul blocco dei canali, ma non capisco cosa significhi con il canale di blocco. Un canale è composto da mittente e ricevente. Il mittente può inviare qualcosa solo in una volta alla volta, il che significa che il ricevitore deve ottenere il pacchetto, finché non può continuare il suo lavoro. Cosa intendi con blocco princip? –