douzhenao6515 2014-07-21 15:41
浏览 63
已采纳

Go:Java的CyclicBarrier之类的可重用屏障?

Using Google Go, I'm trying to sync multiple threads performing an iterative filter on an image. My code basically works like outlined here:

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)
    }

The problem is that I would need a reusable barrier quite like Java's CyclicBarrier, setting the number of threads as its counter value. Unfortunately, the only implementation similar to a barrier I have found is sync.WaitGroup. The WaitGroup however cannot be reset atomically to it's previous counter value. It only offers a normal Wait() function that does not reset the counter value.

Is there any "Go idiomatic" way of achieving what I want or should I rather implement my own CyclicBarrier? Thanks a lot for your help!

  • 写回答

2条回答 默认 最新

  • douyun3799 2014-07-22 05:03
    关注

    You can use sync.Cond to implement CyclicBarrier, see source code of java's CyclicBarrier

    Here is a minimized go version of CyclicBarrier (no timeout, no thread interrupts): 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
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 下图接收小电路,谁知道原理
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测