2

「標準」のセマフォ クラスを Java で実装する方法がわかります。ただし、バイナリ セマフォ クラスを Java で実装する方法がわかりません。そのような実装はどのように機能しますか? セマフォ上のスレッドを起動および停止するには、wake メソッドと notify メソッドをいつ呼び出す必要がありますか? バイナリ セマフォが何であるかは理解していますが、それらをコーディングする方法がわかりません。

編集注:「BINARY」セマフォクラスと言ったことに注意してください。私がすでに行った標準のセマフォクラスは正しいことを知っているので、標準のセマフォクラスには興味がありません。

4

8 に答える 8

4

バイナリ セマフォに対して行った簡単な実装を次に示します。

public class BinarySemaphore {

    private final Semaphore countingSemaphore;

    public BinarySemaphore(boolean available) {
        if (available) {
            countingSemaphore = new Semaphore(1, true);
        } else {
            countingSemaphore = new Semaphore(0, true);
        }
    }

    public void acquire() throws InterruptedException {
        countingSemaphore.acquire();
    }

    public synchronized void release() {
        if (countingSemaphore.availablePermits() != 1) {
            countingSemaphore.release();
        }
    }
}

この実装には、パーミットが 1 つしかないセマフォのカウントでは取得できない、バイナリ セマフォのプロパティが 1 つあります。リリースを複数回呼び出しても、使用可能なリソースは 1 つだけです。このプロパティはここに記載されています。

于 2012-04-27T22:28:26.003 に答える
3

あなたはミューテックス(または相互排他ロック)について話していると思います。その場合は、組み込みロックを使用できます。Javaのこの種のロックはミューテックスとして機能します。つまり、最大で1つのスレッドがロックを所有できます。

synchronized (lock) { 
    // Access or modify shared state guarded by lock 
}

ロックがモックオブジェクトである場合、ロックにのみ使用されます。


編集:

これがあなたのための実装です—値0を使用してロック解除状態を表し、1を使用してロック状態を表す非再入可能相互排除ロッククラス。

class Mutex implements Lock, java.io.Serializable {

    // Our internal helper class
    private static class Sync extends AbstractQueuedSynchronizer {
      // Report whether in locked state
      protected boolean isHeldExclusively() {
        return getState() == 1;
      }

      // Acquire the lock if state is zero
      public boolean tryAcquire(int acquires) {
        assert acquires == 1; // Otherwise unused
        if (compareAndSetState(0, 1)) {
          setExclusiveOwnerThread(Thread.currentThread());
          return true;
        }
        return false;
      }

      // Release the lock by setting state to zero
      protected boolean tryRelease(int releases) {
        assert releases == 1; // Otherwise unused
        if (getState() == 0) throw new IllegalMonitorStateException();
        setExclusiveOwnerThread(null);
        setState(0);
        return true;
      }

      // Provide a Condition
      Condition newCondition() { return new ConditionObject(); }

      // Deserialize properly
      private void readObject(ObjectInputStream s)
          throws IOException, ClassNotFoundException {
        s.defaultReadObject();
        setState(0); // reset to unlocked state
      }
    }

    // The sync object does all the hard work. We just forward to it.
    private final Sync sync = new Sync();

    public void lock()                { sync.acquire(1); }
    public boolean tryLock()          { return sync.tryAcquire(1); }
    public void unlock()              { sync.release(1); }
    public Condition newCondition()   { return sync.newCondition(); }
    public boolean isLocked()         { return sync.isHeldExclusively(); }
    public boolean hasQueuedThreads() { return sync.hasQueuedThreads(); }
    public void lockInterruptibly() throws InterruptedException {
      sync.acquireInterruptibly(1);
    }
    public boolean tryLock(long timeout, TimeUnit unit)
        throws InterruptedException {
      return sync.tryAcquireNanos(1, unit.toNanos(timeout));
    }
  }

どこに電話すればよいかを知る必要がある場合はwait()notify()をご覧くださいsun.misc.Unsafe#park()。java.util.concurrent.locksパッケージ内で使用されます(AbstractQueuedSynchronizer <-LockSupport <-Unsafe)。

お役に立てれば。

于 2011-11-27T15:42:43.270 に答える
2

これはJavaサイトから直接です

Doug Lea が率いる JSR-166 の同時実行ユーティリティ ライブラリは、人気のある同時実行パッケージを J2SE 5.0 プラットフォームに特別にリリースしたものです。スレッド タスク フレームワークであるエグゼキューター、スレッド セーフ キュー、タイマー、ロック (アトミックなものを含む)、およびその他の同期プリミティブを含む、強力で高レベルのスレッド コンストラクトを提供します。

そのようなロックの 1 つは、よく知られているセマフォです。コードのブロックへのアクセスを制限するために、現在使用されている待機と同じ方法でセマフォを使用できます。セマフォはより柔軟で、多数の同時スレッド アクセスを可能にするだけでなく、ロックを取得する前にロックをテストすることもできます。次の例では、バイナリ セマフォとも呼ばれるセマフォを 1 つだけ使用しています。詳細については、java.util.concurrent パッケージを参照してください。

final  private Semaphore s= new Semaphore(1, true);

    s.acquireUninterruptibly(); //for non-blocking version use s.acquire()

try {     
   balance=balance+10; //protected value
} finally {
  s.release(); //return semaphore token
}

waitSemaphore クラスなどの高レベルの抽象化を使用する全体的な理由は、低レベルの/を呼び出す必要がないためだと思いますnotify

于 2011-11-27T15:26:09.023 に答える
2

はい、できます。許可が 1 つのセマフォは、バイナリ セマフォです。それらは、単一のリソースへのアクセスを制御します。それらは、ある種のミューテックス/ロックと見なすことができます。

Semaphore binarySemaphore = new Semaphore(1);
于 2011-11-27T15:28:08.873 に答える
0

Semaphoreクラスの Java 実装のソース コードを確認できます(または直接使用できますか?)。

于 2011-11-27T15:17:41.623 に答える