0

多くのスレッドを保持するプログラムがあります。例として 6 つのスレッドを挙げましょう。そのうちの 5 つは特定のリソースを同時に使用できるはずですが、特定の条件が発生した場合、最後のスレッドは使用できず、その条件が終了するまで待機する必要があります。

私の理解では、ReentrantLock は一度に 1 つのスレッドしか保持できないため、使用できません。一方、セマフォは一度に多くのスレッドで保持できますが、取得メソッドに条件を付ける方法が見つかりません。

この高レベルのオブジェクトはトリックを実行できますか?それとも、通知と待機を直接使用してこの機能を実装する必要がありますか?

例えば。

class A{
   getResource{ ... }
}

//This Runable could be spawn many times at the same time
class B implements Runnable{
   run {
      setConditionToTrue
      getResource
      ...
      getResource
      ...
      getResource
      setConditionToFalse
   }
}

//This will be working forever but only one Thread
class C implements Runnable{
   run{
      loop{
         if(Condition == true) wait
         getResource
      }
   }
}

よろしくお願いします

4

2 に答える 2

2

ここで問題をもう一度言います。B スレッドが共有リソースに同時にアクセスする必要がありますが、C スレッドはリソースを使用する前に何らかの条件が発生するのを待つ必要があります。

あなたの質問を正しく理解できればReentrantLock、問題を解決するために使用できます。

呼び出される新しい関数を導入しgetAccess()、C スレッドがこの関数を呼び出して共有リソースを取得するようにします。共有リソースへのアクセスを許可および停止する関数をさらに 2 つ導入します。

class A {

  private final ReentrantLock lock = new ReentrantLock();
  private Condition someCondition = lock.newCondition();
  private boolean bCondition = false;

  getResource{ ... } // Your existing method used by B threads

  getAccess() { // Protected access to some resource, called by C thread
    lock.acquire();

    try {
      if (!bCondition)
        someCondition.await(); // B thread will wait here but releases the lock
    } finally {
      lock.release();
    }
  }

  allowAccess() { // B thread can call this func to notify C and allow access
    lock.acquire();
    try {
      bCondition = true;
      someCondition.signal(); // Decided to release the resource
    } finally {
      lock.release();
    }
  }

  stopAccess() { // B thread can stop the access
    lock.acquire();
    try {
      bCondition = false;
    } finally {
      lock.release();
    }
  }

}
于 2012-06-23T05:00:26.520 に答える
0

複数のスレッドでリソースを共有する場合は、その共有の意味をより具体的にする必要があります。通常、これは、リソースの現在の値を読み取るスレッドと、値を変更する他のスレッドを区別することを意味します。これは、書き込みが競合せず安定している場合、同時読み取り/排他書き込みパターン (「乗組員」) であることを意味します。

Java API では、これはReentrantReadWriteLockによって提供されます。JCSP で慎重に実装されたCrewなど、検討に値する他の選択肢もあります。

[J]CSP を使用すると、別のパターンも利用できます。共通リソースを独自のスレッドにラップし、すべてのクライアント スレッドから共有 JCSP チャネルを介してそのリソースへのアクセスを提供するパターンです。このクライアント/サーバー パターンは理解と実装が容易であり、スレッド通信グラフが非循環であるため、正式にデッドロックがないという追加の利点があります (詳細)。

于 2012-06-24T08:16:48.583 に答える