1と0で初期化されたセマフォの違いを教えてください。以下のように:
public static Semaphore semOne = new Semaphore(1);
そして
public static Semaphore semZero = new Semaphore(0);
セマフォインスタンスの引数は、使用可能な「許可」の数です。 0または1だけでなく、任意の整数にすることができます。
semZero
の場合、acquire()
を実行するまで、すべてのtryAcquire()
呼び出しはブロックされ、release()
呼び出しはfalseを返します。
semOne
の場合、最初のacquire()
呼び出しは成功し、残りは最初の呼び出しが解放されるまでブロックされます。
クラスは十分に文書化されています ここ 。
パラメータ:permits-使用可能な許可の初期数。この値は負の場合があります。その場合、取得が許可される前にリリースが発生する必要があります。
コンストラクターパラメーターpermits
(初期セマフォカウンター)は、カウンター(許可)がゼロになる前に実行できるSemaphore.aquire()
の呼び出し数であり、acquire()
blocksです。
1は通常の値であり、1つのスレッドのみが取得を通過するようにします。
semaphore.acquire();
try {
// Critical region
...
} finally {
semaphore.release();
}
の使用法については、 ここ を参照してください。
セマフォは、並行性の低レベルのメカニズムです。つまり、スレッドの実行をブロックするゼロに達したときのカウンターです。これは Dijkstra に由来します。ここで、バイナリセマフォ(0、1)は、パス(0の場合は停止、パス--permits)と言う鉄道セマフォのメタファーであり、保護されたトラックの最後でリリースを行います(++許可)。
セマフォのドキュメントを最初に読んだときも、説明を誤解していました。私が見逃した主なポイントは、「...最初の許可数...」の一部でした。どういうわけか私はこれが最大として利用できる許可の数になるでしょうが、そうではありません。最終的に、セマフォは任意の数からカウントアップしますが、セマフォの許可が1を超えた場合にのみ、(取得を使用する)待機中のスレッドを有効にします。
(スレッド化されていない)コードの単純な部分もこれを示しています:
@Test
public void testNegativeSemaphore()
{
Semaphore semaphore = new Semaphore(-2);
assertEquals(-2, semaphore.availablePermits());
semaphore.release();
assertEquals(-1, semaphore.availablePermits());
semaphore.release();
assertEquals(0, semaphore.availablePermits());
semaphore.release();
assertEquals(1, semaphore.availablePermits());
}
コードが示すように、使用可能な許可はリリースごとに増加しますが、値が1以上に達すると、他のスレッドが許可を取得できるようになります。
そこからavailablePermitsは、aqcuireを使用して負になることはできないことに注意してください。許可が0の場合、セマフォの要点は、許可が再び使用可能になるのを待つことです。