5

私には2つの方法があります:a()b()。複数のスレッドが同時に任意のメソッドにアクセスすることは問題ありませんが(これは望ましいことです)、実行a()中にスレッドを入力したくありませんb()。それ、どうやったら出来るの?

編集1

4つのスレッドがあり、Thread 1にアクセスしているとしましょうA()。私が欲しいのは、4つのスレッドすべてが使用すべきではないということB()です。

4

3 に答える 3

6

下部にある更新を確認してください-このアプローチは機能しないと思います。情報のためにそれを残します。


セマフォを使用できます:

  • スレッドがにある場合、b()実行しようとしているスレッドは、a()の実行が終了するまでブロックさb()れます。
  • スレッドが入っb()ていて、2番目のスレッドが実行しようとすると、次のb()ことが可能になります。
  • a()実行されていないときに2つのスレッドが実行b()されると、両方が実行されます

注:スレッドが入っa()て「セマフォテスト」に合格すると、別のスレッドが終了するb()前に実行を開始できます。a()

原則は機能するはずですが、私はそれをテストしていません。

private final Semaphore inB = new Semaphore(1);

public void a() throws InterruptedException {
    inB.acquire(); //blocks until no thread is in b any longer
    //now we are good to go and execute a()
    //release the semaphore immediately for other threads who want to run a()
    inB.release(); 
    //rest of your code here
}
public void b() {
    //does not block to allow 2 thread running b() simultaneously
    boolean needToRelease = inB.tryAcquire(); 
    //rest of your code
    //if the permit was acquired, release it to allow threads to run a()
    if (needToRelease) {
        inB.release();
    }
}

編集

あなたの意図は明確ではなく、あなたのコメントの1つが相互に排他的でありたいa()と言っているので、あなたの質問は編集されました(多くのスレッドはどちらかまたは並列に実行できますが、並列に実行してはいけません)。その場合、2つのセマフォとで同じロジックを使用できます。b()a()b()a()b()inAinB


更新=>バグ

別の回答へのコメントで@yshavitが指摘しているように、次のシナリオのコードには競合状態があります。

  • T1が実行a()され、取得されますinB
  • T2が実行b()され、取得に失敗しますinB
  • T1リリースinB
  • T2が実行されているにもかかわらず、T3が実行a()され、なんとか取得できますinBb()

これはSempahoresだけでは達成できないようです。この答えはより良い解決策を与えます。

于 2012-11-10T09:14:50.433 に答える
3

簡単にするために例外処理は省略されています。

public class Test {
  private final Object lock = new Object();
  private int counterA;
  private int counterB;

  public void a() {
    synchronized(lock) {
      while(counterB > 0) {
        lock.wait();
      }
      ++counterA;
    }

    // do work

    synchronized(lock) {
      --counterA;
      lock.notifyAll();
    }
  }

  public void b() {
    synchronized(lock) {
      while(counterA > 0) {
        lock.wait();
      }
      ++counterB;
    }

    // do work

    synchronized(lock) {
      --counterB;
      lock.notifyAll();
    }
  }
}
于 2012-11-10T09:37:56.660 に答える
1

java.util.concurrent.locksは、いくつかのロックを含むJavaパッケージです。

a()ロックを取り、最後にそれを解放しますa()

b()、同じロックで同じことを行います

非対称の動作を処理したい場合は、ReadWriteLockを使用できます。a ()はリーダーで、b()はライターです。いくつかのb()はロックしますが、いくつかのa()はロックしません。

于 2012-11-10T09:22:40.093 に答える