【问题标题】:Implementing a cyclicbarrier in java using semaphores使用信号量在java中实现循环障碍
【发布时间】:2013-04-01 23:55:02
【问题描述】:

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

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

【问题讨论】:

  • 我不应该使用内置的 cyclicBarrier :)
  • 是的,信号量也是 :)
  • 当只有一个线程被释放时,我讨厌使用notifyAll()。
  • 我认为你不能使用AtomicInteger 和朋友?
  • 我不知道什么是 AtomicInteger... 我应该绑定 2 根氢线和 1 根氧线。即每 2 个氢气线程在屏障处等待,直到氧气线程到达,然后所有线程都被执行。我已经追踪了一切,所以我几乎可以肯定问题出在障碍物上。问题是我看不出问题出在哪里:S

标签: java multithreading semaphore cyclicbarrier


【解决方案1】:

我看到您正在使用来自The Little Book of Semaphores 的解决方案。本书的一个要点是,您可以使用信号量作为唯一的协调原语来解决许多协调问题。使用 synchronized 来实现信号量是非常好的,因为这是正确执行的必要条件。然而,在解决本应使用信号量解决的难题的方法中使用 同步 却忽略了这一点。

另外,我认为它不适用于您的情况:您不会在 this.turnstile.down() 处陷入僵局吗?您阻塞了一个信号量,该信号量在对象和方法上持有排他锁(通过同步),这将允许该信号量被释放。

解决上述问题:您向线程发出信号,表示它们可以通过从 barrier.down() 返回来继续。您可以通过 turnstile.down() 确保不会过早返回。

旁白:信号量实现

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

旁白:其他同步原语

请注意,java 构造 synchronized、.wait() 和 .notify() 对应于 Monitor 协调原语。使用监视器(或其他协调原语)而不是信号量来解决难题可能是有益的,但我建议将这些努力分开。尝试使用 Haskell's Software Transactional Memory 解决难题时,我获得了一些乐趣。

旁白:关于可运行性

你说你已经尝试了一些东西,这表明你有一些代码可以让你运行问题中的代码。如果您包含该代码会很有帮助,因此我们也可以轻松运行它。我可能会检查我假设的死锁是否真的发生了。

【讨论】:

    猜你喜欢
    • 2014-09-07
    • 2013-03-21
    • 2013-11-30
    • 2012-12-09
    • 2013-12-07
    • 2011-09-13
    • 1970-01-01
    • 2018-05-11
    • 2020-05-18
    相关资源
    最近更新 更多