0

問題は次のとおりです。バリアは 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--;
    }
}
4

1 に答える 1

1

The Little Book of Semaphoresのソリューションを使用しているようです。この本の主なポイントの 1 つは、セマフォを唯一の調整プリミティブとして使用して、多くの調整問題を解決できるということです。Synchronizedを使用してセマフォを実装することはまったく問題ありません。それは正しく行うために必要だからです。ただし、セマフォで解決されるはずのパズルを解決するメソッドで同期を使用することはポイントを逃しています。

また、あなたの場合はうまくいかないと思います: this.turnstile.down()でデッドロックが発生しませんか? そのセマフォが解放されることを可能にするオブジェクトとメソッドに対して( synchronizedを介して)排他ロックを保持するセマフォをブロックします。

述べたように質問に対処します: スレッドに、barrier.down()から戻ることによって続行できることを通知します。turntile.down()を実行して、すぐに戻らないようにします。

余談: セマフォの実装

セマフォの実装は正しいように見えますが、少なくとも非標準である非負の初期値のみを許可する点が異なります。私には見えない、これを行う動機はありますか?負の初期値が間違っていると思われる場合は、黙って何か他のことをするのではなく、エラーをスローしてみませんか?

余談: その他の同期プリミティブ

java 構成のsynchronized.wait()、および.notify()は、モニター調整プリミティブに対応することに注意してください。セマフォの代わりにモニター (または他の調整プリミティブ) を使用してパズルを解くことは有益かもしれませんが、それらの作業は別にしておくことをお勧めします。Haskell の Software Transactional Memoryを使用してパズルを解こうとして、少し楽しくなりました。

余談: 走行性について

これは、質問のコードを実行できるコードがあることを示しています。そのコードを含めていただければ、私たちも簡単に実行できるので助かりました。おそらく、仮説のデッドロックが実際に発生することを確認したでしょう。

于 2014-11-11T11:18:37.580 に答える