2016-09-29 41 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()