2016-09-29 42 views
2

我有整數的片,其被同時操縱:如何等待緩衝通道(信號量)爲空?

ints := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 

以具有上限同時運行的去例程我使用的緩衝信道作爲旗語:

sem := make(chan struct{}, 2) 

for _, i := range ints { 
    // acquire semaphore 
    sem <- struct{}{} 

    // start long running go routine 
    go func(id int, sem chan struct{}) { 
    // do something 

    // release semaphore 
    <- sem 
    }(i, sem) 
} 

上面的代碼工作得很好,直到最後一個或最後兩個整數達到了,因爲那些最後走程序完成之前,程序結束。

問題:我怎麼等待緩衝通道地漏?

+0

你必須使用一個互斥體或東西。緩衝的通道在滿時會阻塞,但沒有任何語言功能會阻塞,直到它爲空。 – evanmcdonnal

回答

8

不能使用以該方式信號量(在這種情況下信道)。不能保證在處理值和調度更多的goroutine時,它不會有空的任何一點。在這種情況下,這不是特別關注的問題,因爲您正在同步調度工作,但由於沒有比賽方式來檢查頻道的長度,所以沒有等待頻道長度達到0的原語。

使用sync.WaitGroup等待所有goroutines完成

​​
+1

謝謝,我也想過使用'WaitGroup'。這感覺就像正確的方式! – Kiril

0

很明顯,沒有人等待你的例程完成。因此,程序在最後2個程序完成之前結束。在程序結束之前,您可以使用工作組來等待所有的例行程序完成。這更好的告訴它 - https://nathanleclaire.com/blog/2014/02/15/how-to-wait-for-all-goroutines-to-finish-executing-before-continuing/

+0

謝謝你,我一直在尋找如何避免這種情況,並且有'WorkGroup'完美的作品。 JimB的答案澄清了這一點 – Kiril

2

使用「工作池」來處理你的數據。它比跑夠程爲每個 INT幼兒,對裏面的變量分配內存等等...

ints := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 

ch := make(chan int) 

var wg sync.WaitGroup 

// run worker pool 
for i := 2; i > 0; i-- { 
    wg.Add(1) 

    go func() { 
     defer wg.Done() 

     for id := range ch { 
      // do something 
      fmt.Println(id) 
     } 
    }() 
} 

// send ints to workers 
for _, i := range ints { 
    ch <- i 
} 

close(ch) 

wg.Wait()