JAVAマルチスレッド--信号量(Semaphore)
概要
信号量(Semaphore)は、信号灯と呼ばれる場合があり、マルチスレッド環境で使用される施設であり、各スレッドを調整して、公共資源を正確かつ合理的に使用できることを保証する.
1カウント信号量.概念的には、信号量はライセンスセットを維持する.必要に応じて、ライセンスが使用可能になる前に各acquire()がブロックされ、ライセンスが取得されます.各release()にライセンスが追加され、ブロックされている取得者が解放される可能性があります.ただし,実際のライセンスオブジェクトを使用せずに,Semaphoreは利用可能なライセンスの番号のみをカウントし,対応する行動をとる.信号量を取得したスレッドはコードに入ることができます.そうしないと待ちます.アクセス許可はacquire()とrelease()で取得および解放されます.
コンセプト Semaphoreは単一値と多値の2種類に分けられ,前者は1つのスレッドのみで得られ,後者は複数のスレッドで得ることができる.
1つの駐車場の運営を例に挙げます.簡単にするために、駐車場が3つしかないと仮定し、最初は3つの駐車スペースが空いていました.この時、同時に5台の車が来たら、番人はそのうち3台が邪魔されずに入ることを許可し、車を置いて止め、残りの車は入り口で待たなければならず、その後の車も入り口で待たなければならない.この時、1台の車が駐車場を離れ、門番が知った後、車を開けて止め、1台を入れ、また2台を離れたら、また2台を入れて、このように往復することができます.
この駐車場システムでは、駐車スペースは公共資源であり、各車はスレッドのようなもので、ドアマンが信号量の役割を果たしている.
さらに、信号量の特性は、信号量が非負の整数(駐車スペース数)であり、そのスレッド(車両)を通過するすべてのスレッドがその整数を1つ減らし(もちろんリソースを使用するため)、整数値がゼロの場合、そのスレッドを通過しようとするすべてのスレッドが待機状態になる.信号量について,Wait(待機)とRelease(解放)の2つの動作を定義した.スレッドがWait(待機)動作を呼び出すと、信号量が1より大きいかタイムアウトするまで、信号量を1つ減らすか、ずっと待つかのいずれかです.Release(リリース)は、実際には信号量に加算操作を行い、車両が駐車場を離れることに対応している.この操作を「リリース」と呼ぶのは、加算操作が実際には信号量によって守られている資源を解放しているからである.
Javaでは、この信号量が公平モードを採用するかどうかを設定することもでき、公平に実行されると、スレッドは到着した順序(FIFO)で実行され、不公平であれば、後で要求される可能性のあるキューのヘッダに並ぶこともできる.JDKでは次のように定義されています. Semaphore(int permits, boolean fair) 指定されたライセンス数と指定された公平な設定を持つSemaphoreを作成します.
Semaphoreは現在マルチスレッド環境で拡張されて使用されており,オペレーティングシステムの信号量は重要な概念であり,プロセス制御に応用されている.JavaコンカレントライブラリSemaphoreは信号量制御を簡単に完了でき、Semaphoreはリソースが同時にアクセスできる個数を制御し、acquire()を通じてライセンスを取得し、なければ待機し、release()はライセンスを解放することができる.たとえばWindowsで共有ファイルの最大クライアントアクセス数を設定できます.
Semaphoreが実現した機能はトイレに5つの穴があるようなもので、10人がトイレに行くとしたら、同時に何人がトイレに行くしかないのでしょうか.同時に5人しか占有できないが、5人のうちのいずれかが譲った後、待機していた他の5人のうち1人が占有できるようになった.また、待機している5人の中では、Semaphoreオブジェクトを構築する際に入力されるパラメータオプションに応じて、ランダムに優先順位を獲得してもよいし、先着順に機会を獲得してもよい.単一信号量のSemaphoreオブジェクトは、反発ロックの機能を実現することができ、一方のスレッドによって「ロック」が得られ、他方のスレッドによって「ロック」が解放されることができ、これはデッドロック回復の場合に適用することができる.
コードの例
信号量(Semaphore)は、信号灯と呼ばれる場合があり、マルチスレッド環境で使用される施設であり、各スレッドを調整して、公共資源を正確かつ合理的に使用できることを保証する.
1カウント信号量.概念的には、信号量はライセンスセットを維持する.必要に応じて、ライセンスが使用可能になる前に各acquire()がブロックされ、ライセンスが取得されます.各release()にライセンスが追加され、ブロックされている取得者が解放される可能性があります.ただし,実際のライセンスオブジェクトを使用せずに,Semaphoreは利用可能なライセンスの番号のみをカウントし,対応する行動をとる.信号量を取得したスレッドはコードに入ることができます.そうしないと待ちます.アクセス許可はacquire()とrelease()で取得および解放されます.
コンセプト Semaphoreは単一値と多値の2種類に分けられ,前者は1つのスレッドのみで得られ,後者は複数のスレッドで得ることができる.
1つの駐車場の運営を例に挙げます.簡単にするために、駐車場が3つしかないと仮定し、最初は3つの駐車スペースが空いていました.この時、同時に5台の車が来たら、番人はそのうち3台が邪魔されずに入ることを許可し、車を置いて止め、残りの車は入り口で待たなければならず、その後の車も入り口で待たなければならない.この時、1台の車が駐車場を離れ、門番が知った後、車を開けて止め、1台を入れ、また2台を離れたら、また2台を入れて、このように往復することができます.
この駐車場システムでは、駐車スペースは公共資源であり、各車はスレッドのようなもので、ドアマンが信号量の役割を果たしている.
さらに、信号量の特性は、信号量が非負の整数(駐車スペース数)であり、そのスレッド(車両)を通過するすべてのスレッドがその整数を1つ減らし(もちろんリソースを使用するため)、整数値がゼロの場合、そのスレッドを通過しようとするすべてのスレッドが待機状態になる.信号量について,Wait(待機)とRelease(解放)の2つの動作を定義した.スレッドがWait(待機)動作を呼び出すと、信号量が1より大きいかタイムアウトするまで、信号量を1つ減らすか、ずっと待つかのいずれかです.Release(リリース)は、実際には信号量に加算操作を行い、車両が駐車場を離れることに対応している.この操作を「リリース」と呼ぶのは、加算操作が実際には信号量によって守られている資源を解放しているからである.
Javaでは、この信号量が公平モードを採用するかどうかを設定することもでき、公平に実行されると、スレッドは到着した順序(FIFO)で実行され、不公平であれば、後で要求される可能性のあるキューのヘッダに並ぶこともできる.JDKでは次のように定義されています. Semaphore(int permits, boolean fair) 指定されたライセンス数と指定された公平な設定を持つSemaphoreを作成します.
Semaphoreは現在マルチスレッド環境で拡張されて使用されており,オペレーティングシステムの信号量は重要な概念であり,プロセス制御に応用されている.JavaコンカレントライブラリSemaphoreは信号量制御を簡単に完了でき、Semaphoreはリソースが同時にアクセスできる個数を制御し、acquire()を通じてライセンスを取得し、なければ待機し、release()はライセンスを解放することができる.たとえばWindowsで共有ファイルの最大クライアントアクセス数を設定できます.
Semaphoreが実現した機能はトイレに5つの穴があるようなもので、10人がトイレに行くとしたら、同時に何人がトイレに行くしかないのでしょうか.同時に5人しか占有できないが、5人のうちのいずれかが譲った後、待機していた他の5人のうち1人が占有できるようになった.また、待機している5人の中では、Semaphoreオブジェクトを構築する際に入力されるパラメータオプションに応じて、ランダムに優先順位を獲得してもよいし、先着順に機会を獲得してもよい.単一信号量のSemaphoreオブジェクトは、反発ロックの機能を実現することができ、一方のスレッドによって「ロック」が得られ、他方のスレッドによって「ロック」が解放されることができ、これはデッドロック回復の場合に適用することができる.
コードの例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* DateTime: 2015 1 1 6:41:01
*
*/
public class SemaPhore {
public static void main(String[] args) {
//
ExecutorService exec = Executors.newCachedThreadPool();
// 5
final Semaphore semp = new Semaphore(5);
// 20
for (int index = 0; index < 50; index++) {
final int NO = index;
Runnable run = new Runnable() {
public void run() {
try {
//
semp.acquire();
System.out.println("Accessing: " + NO);
Thread.sleep((long) (Math.random() * 6000));
// ,
semp.release();
//availablePermits()
System.out.println("-----------------" + semp.availablePermits());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
exec.execute(run);
}
//
exec.shutdown();
}
}