2014-01-29 32 views
1

我使用Go構建了一個工作系統的骨架,我得到了「致命的錯誤:所有的goroutines都睡着了 - 僵局!」。所有去的例程都睡着了 - 死鎖

我使用兩個通道進行協調,一個創建作業,第二個發送結果。創建作業後,關閉輸入通道。

我的問題是我如何關閉輸出通道,以便程序可以正確退出。 的代碼是:

package main 

import (
    "bufio" 
    "flag" 
    "fmt" 
    "log" 
    "math/rand" 
    "os" 
    "time" 
) 

type Work struct { 
    id int 
    ts time.Duration 
} 

const (
    NumWorkers = 5000 
    NumJobs = 100000 
) 

func worker(in <-chan *Work, out chan<- *Work) { 
    for w := range in { 
     st := time.Now() 
     time.Sleep(time.Duration(rand.Int63n(int64(200 * time.Millisecond)))) 
     w.ts = time.Since(st) 
     out <- w 
    } 
} 

func main() { 
    wait := flag.Bool("w", false, "wait for <enter> before starting") 
    flag.Parse() 

    if *wait { 
     fmt.Printf("I'm <%d>, press <enter> to continue", os.Getpid()) 
     reader := bufio.NewReader(os.Stdin) 
     reader.ReadString('\n') 
    } 

    Run() 
} 

func Run() { 
    in, out := make(chan *Work, 100), make(chan *Work, 100) 
    for i := 0; i < NumWorkers; i++ { 
     go worker(in, out) 
    } 
    go createJobs(in) 
    receiveResults(out) 
} 

func createJobs(queue chan<- *Work) { 
    for i := 0; i < NumJobs; i++ { 
     work := &Work{i, 0} 
     queue <- work 
    } 
    close(queue) 
} 

func receiveResults(completed <-chan *Work) { 
    for w := range completed { 
     log.Printf("job %d completed in %s", w.id, w.ts) 
    } 
} 

任何幫助表示讚賞:)

+0

有大量的印刷,有助於診斷此類問題 – Arjan

回答

1

我錯過了你的一部分知道僵局的原因在原來的答案。

  • 你提到WaitGroup,這基本上是一個信號
  • 你可以使用另一種 「控制」 頻道工人時,他們完成

上打了個平手 -

func worker(ctrl chan<- bool, in <-chan *Work, out chan<- *Work) { 
    for w := range in { 
     st := time.Now() 
     time.Sleep(time.Duration(rand.Int63n(int64(200 * time.Millisecond)))) 
     w.ts = time.Since(st) 
     out <- w 
    } 
    ctrl <- true 
} 

func control(ctrl <-chan bool, numWorkers int, out chan<- *Work) { 
    for i=0; i<numWorkers; i++ { 
     <-ctrl 
    } 
    close(out) 
} 

原回答:

你做了range就完成了:

for w := range completed { 
    log.Printf("job %d completed in %s", w.id, w.ts) 
} 

但通道被永遠不會關閉

+0

正確的信息(gorutines的狀態)。我想用WaitGroup關閉已完成的頻道,因爲我沒有其他辦法。 –

+0

我錯過了你描述中的最後一句話。那麼這是一個可能的解決方案。 – Arjan

+0

Arjan,我按照你的建議使用控制通道,非常感謝:) –

相關問題