2016-04-21 9 views
0

Ich lernte Goroutines, und wurde zwei Scheiben miteinander in zwei Goroutines verglichen, die in einer Endlosschleife ist, um es für immer zu vergleichen, was nicht sein kann das beste Beispiel zu verwenden, und ich konnte nicht herausfinden, warum es hängt.Hung goroutines beim Vergleich zweier Scheiben in zwei separaten goroutines und mit sync.Waitgroup

for ;; { 
    var wg sync.WaitGroup 
    wg.Add(2) 
    go FindinFirst(&Arr1, &Arr2, AddChan, &wg) 
    go FindinSecond(&Arr2, &Arr1, DelChan, &wg) 
    counter := 0 
     for ; ; { 
      select { 
      case Add, ok := <- AddChan: 
       if ok == true { 
        for k, v := range Add { 
         fmt.Println(k, ":", v) 
        } 
       }else { 
        counter += 1 
       } 
      case Del, ok := <- DelChan: 
       if ok == true { 
        for k, v := range Del { 
         fmt.Println(k, ":", v) 
        } 
       }else { 
        counter += 1 
        } 
      } 
      if counter == 2{ 
       break 
      } 
      wg.Wait() 
} 

Funktion FindinFirst ist

func FindinFirst(Arr1, Arr2 *[]string, AddChan chan string, wg *sync.WaitGroup){ 
defer wg.Done() 
fmt.Println("Starting FindinFirst") 
defer close(AddChan) 
for _, i := range *Arr1 { 
    if IfExists(i, *Arr2) { 
     fmt.Println("Exists") 
     continue 
    } else { 
     AddChan <- i 

    } 
} 
} 

Funktion FindinSecond ist

func FindinSecond(Arr2, Arr1 *[]string, DelChan chan string, wg *sync.WaitGroup){ 
defer wg.Done() 
fmt.Println("Starting FindinSecond") 
defer close(DelChan) 
for _, i := range *Arr2 { 
    if IfExists(i, *Arr1) { 
     fmt.Println("Exists") 
     continue 
    } else { 
     DelChan <- i 

    } 
} 
} 

Und IfExists ist nur eine Funktion, die einen bool zurück, wenn der Wert in der Schicht vorhanden ist.

Die Routine ist jedoch mit nur einem Wert fest, der gedruckt wird, und ich bin nicht sicher, warum es passiert. Beide Scheiben haben fast 1000 Werte und beide haben Unikate. Was ist falsch an dem Code?

Antwort

2

Ich glaube nicht, dass hier die Verwendung von Wartegruppen verwendet wird ... Da Sie die Kanäle innerhalb einer for-Schleife verwenden, blockiert das Setzen von wg.wait(), bis alle Wartegruppen abgeschlossen sind.

In diesen Fällen wird das Hinzufügen eines Werts in AddChan blockiert, sofern nicht jemand darauf wartet. Der Code funktioniert nur für den ersten Fall, nach dem es hängt.

Sie können die wg.wait() und äußere for-Schleife entfernen und es wird funktionieren.

func main() { 
    Arr1 := []string{"a", "b", "c", "d"} 
    Arr2 := []string{"c", "e", "f", "g"} 
    AddChan := make(chan string) 
    DelChan := make(chan string) 

    var wg sync.WaitGroup 
    wg.Add(2) 
    go FindinFirst(&Arr1, &Arr2, AddChan, &wg) 
    go FindinSecond(&Arr2, &Arr1, DelChan, &wg) 
    counter := 0 
    for { 
     select { 
     case Add, ok := <-AddChan: 
      if ok == true { 
       fmt.Println(Add) 
      } else { 
       counter += 1 
      } 
     case Del, ok := <-DelChan: 
      if ok == true { 
       fmt.Println(Del) 
      } else { 
       counter += 1 
      } 
     } 

     //if both the channels are closed, we are good, hence exit 
     if counter == 2 { 
      break 
     } 
    } 
}