使用信号量在Java中实现循环屏障 [英] Implementing a cyclicbarrier in java using semaphores

查看:184
本文介绍了使用信号量在Java中实现循环屏障的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题如下,因为仅使用down()调用了屏障,所以它将等待n个线程到达,然后在关键区域中一起执行所有n个线程,现在如何我是否通知调用 barrier.down 的线程可以继续运行.我尝试在 phase2()之后添加 notifyAll(),但这不起作用.帮助? :)

The question is as follows, since the barrier is only called using down() so that it would wait for the n threads to arrive and then execute all n threads together in the critical region now how do I inform the threads calling on barrier.down that it can move on now. I tried adding notifyAll() after phase2() and that doesn't work. Help? :)

public class cyclicBarrier {
    private int n;
    private int count;
    private semaphore mutex;
    private semaphore turnstile;
    private semaphore turnstile2;

    public cyclicBarrier(int n){
        this.n = n;
        this.count = 0;
        this.mutex = new semaphore(1);
        this.turnstile = new semaphore(0);
        this.turnstile2 = new semaphore(0);
    }

    public synchronized void down() throws InterruptedException{
        this.phase1(); //waits for n threads to arrive
        this.phase2(); //waits for n threads to execute
    }

    private synchronized void phase1() throws InterruptedException {
        this.mutex.down();
        this.count++;
        if(this.count == this.n){
            for(int i = 0; i < this.n; i++){
                this.turnstile.signal(); //when n threads received then move on to phase 2
            }
        }
        this.mutex.signal();
        this.turnstile.down(); //keeps waiting till I get n threads
    }

    private synchronized void phase2() throws InterruptedException {
        this.mutex.down();
        this.count--;
        if(this.count == 0){
            for(int i = 0; i < this.n; i++){
                this.turnstile2.signal(); //reset the barrier for reuse 
            }
        }
        this.mutex.signal();
        this.turnstile2.down(); //keeps waiting till n threads get executed
    }
}


public class semaphore {
    private int counter;

    public semaphore(int number){
        if (number > 0) {
            this.counter = number;
        }
    }

    public synchronized void signal(){
        this.counter++;
        notifyAll();
    }

    public synchronized void down() throws InterruptedException{
        while (this.counter <= 0){
            wait();
        }
        this.counter--;
    }
}

推荐答案

我看到您正在使用 信号量小书 .本书的一个重点是您可以使用信号量作为唯一的协调原语来解决许多协调问题.最好使用 synchronized 来实现信号量,因为这样做是正确的.但是,它错过了要点,即在解决应该由信号量解决的难题的方法中使用 synchronized .

I see you're using the solution from The Little Book of Semaphores. One main point of the book is that you can solve many coordination problems using semaphores as the only coordination primitive. It is perfectly fine to use synchronized to implement a semaphore, since that is necessary to do it correctly. It misses the point, however, to use synchronized in the methods which solve a puzzle that is supposed to be solved with semaphores.

此外,我认为这对您而言不起作用:您是否在 this.turnstile.down()上陷入僵局?您阻止了一个信号灯,该信号灯在对象和方法上持有排他锁(通过同步),这将使该信号灯得以释放.

Also, I think it doesn't work in your case: don't you get a deadlock at this.turnstile.down()? You block on a semaphore which holding an exclusive lock (through synchronized) on the object and method which would allow that semaphore to get released.

按以下所述解决问题:您向线程发出信号,可以从 barrier.down()返回来继续进行操作.您可以通过执行 turnstile.down()来确保不会过早返回.

Addressing the question as stated: you signal to threads that they can proceed by returning from barrier.down(). You ensure that you don't return too soon by doing turnstile.down().

此外:信号量的实现

您的信号量实现看起来正确,只是您只允许使用非负初始值,该值至少是非标准的.我看不到这样做的动力吗?如果您认为负初始值是错误的,为什么不抛出错误而不是默默地做其他事情?

Your semaphore implementation looks correct, except that you only allow non-negative initial values, which is at least non-standard. Is there some motivation for doing this that I can't see? If you think negative initial values are wrong, why not throw an error instead of silently doing something else?

旁边:其他同步原语

请注意,Java构造 synchronized ,, .wait() .notify()对应于 Haskell的软件事务性存储器.

Note that the java constructs synchronized, .wait() and .notify() correspond to the Monitor coordination primitive. It may be instructive to solve the puzzles with monitors (or other coordination primitives) instead of semaphores, but I would recommend keeping those efforts separate. I've had a bit of fun trying to solve a puzzle using Haskell's Software Transactional Memory.

旁边:可运行性

您说您已经尝试过一些事情,这表明您有一些代码可以运行问题中的代码.如果您包含了该代码,那将很有帮助,因此我们也可以轻松地运行它.我可能会检查出我假设的死锁确实发生了.

You say you have tried things, which indicates that you have some code that allows you to run the code in the question. It would have been helpful if you had included that code, so we could easily run it too. I probably would have checked that my hypothesized deadlock actually occurs.

这篇关于使用信号量在Java中实现循环屏障的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆