我正在尝试使用Google Go同步多个线程,以对图像执行迭代过滤。我的代码基本上像这里概述的那样工作:
func filter(src *image.Image, dest *image.Image, start, end, runs int, barrier ??) {
for i:= 0; i < runs; i++ {
// ... do image manipulation ...
// barrier.Await() would work here
if start == 1 {
// the first thread switches the images for the next iteration step
switchImgs(src, dest)
}
// barrier.Await() again
}
}
func main() {
//...
barrier := sync.BarrierNew(numberOfThreads)
for i := 0; i < numberOfThreads; i++ {
go filter(..., barrier)
}
问题是我需要一个可重用的屏障,就像Java的
CyclicBarrier
一样,将线程数设置为其计数器值。不幸的是,我发现的唯一类似于障碍的实现是sync.WaitGroup
。但是,WaitGroup
不能自动重置为其先前的计数器值。它仅提供普通的Wait()
函数,不会重置计数器值。有什么“惯用的”方式来实现我想要的,还是我应该实现自己的
CyclicBarrier
?非常感谢你的帮助! 最佳答案
您可以使用sync.Cond实现CyclicBarrier,请参见source code of java's CyclicBarrier
这是CyclicBarrier的最小化版本(无超时,无线程中断):
http://play.golang.org/p/5JSNTm0BLe
type CyclicBarrier struct {
generation int
count int
parties int
trip *sync.Cond
}
func (b *CyclicBarrier) nextGeneration() {
// signal completion of last generation
b.trip.Broadcast()
b.count = b.parties
// set up next generation
b.generation++
}
func (b *CyclicBarrier) Await() {
b.trip.L.Lock()
defer b.trip.L.Unlock()
generation := b.generation
b.count--
index := b.count
//println(index)
if index == 0 {
b.nextGeneration()
} else {
for generation == b.generation {
//wait for current generation complete
b.trip.Wait()
}
}
}
func NewCyclicBarrier(num int) *CyclicBarrier {
b := CyclicBarrier{}
b.count = num
b.parties = num
b.trip = sync.NewCond(&sync.Mutex{})
return &b
}