2016-07-12 36 views
4

Wie gehe ich mit einer Situation, wo unerkannt Deadlock auftritt, wenn Ergebnisse der Ausführung von unsicheren Anzahl Aufgaben aus einem Kanal in einem komplexen Programm, z. Webserver?Undected "Deadlock" beim Lesen von Kanal

package main 

import (
    "fmt" 
    "math/rand" 
    "time" 
) 

func main() { 
    rand.Seed(time.Now().UTC().UnixNano()) 

    results := make(chan int, 100) 

    // we can't know how many tasks there will be 
    for i := 0; i < rand.Intn(1<<8)+1<<8; i++ { 
     go func(i int) { 
      time.Sleep(time.Second) 
      results <- i 
     }(i) 
    } 

    // can't close channel here 
    // because it is still written in 
    //close(results) 

    // something else is going on other threads (think web server) 
    // therefore a deadlock won't be detected 
    go func() { 
     for { 
      time.Sleep(time.Second) 
     } 
    }() 

    for j := range results { 
     fmt.Println(j) 
     // we just stuck in here 
    } 
} 

Bei einfacheren Programmen gehen Sie detects a deadlock and properly fails. Die meisten Beispiele holen entweder eine bekannte Anzahl von Ergebnissen oder schreiben sequentiell in den Kanal.

+0

Dies ist nicht wirklich ein Deadlock - Sie haben nicht zwei Threads auf eine Ressource streit, haben Sie einen Thread auf Daten warten, die nie gehen zu kommen ist. Es gibt keine Verriegelung. – Adrian

+0

In go Fehlermeldung eine sehr ähnliche Situation ruft für einen Deadlock: 'throw: alle goroutines schlafen - Deadlock!'; aber ich sehe deinen Standpunkt – sanmai

Antwort

7

Der Trick besteht darin, sync.WaitGroup zu verwenden und darauf zu warten, dass die Aufgaben nicht blockierend abgeschlossen werden.

var wg sync.WaitGroup 

// we can't know how many tasks there will be 
for i := 0; i < rand.Intn(1<<8)+1<<8; i++ { 
    wg.Add(1) 
    go func(i int) { 
     time.Sleep(time.Second) 
     results <- i 
     wg.Done() 
    }(i) 
} 

// wait for all tasks to finish in other thread 
go func() { 
    wg.Wait() 
    close(results) 
}() 

// execution continues here so you can print results 

Siehe auch: Go Concurrency Patterns: Pipelines and cancellation - The Go Blog