セマフォ-初期カウントの用途は何ですか?


91

http://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim.aspx

セマフォを作成するには、初期カウントと最大カウントを指定する必要があります。MSDNによると、初期カウントは-

同時に許可できるセマフォの最初の要求数。

最大数は

同時に許可できるセマフォのリクエストの最大数。

最大数は、リソースに同時にアクセスできるスレッドの最大数であることが理解できます。しかし、初期カウントの使用は何ですか?

初期カウントが0で最大カウントが2のセマフォを作成すると、どのスレッドプールスレッドもリソースにアクセスできなくなります。初期カウントを1に設定し、最大カウントを2に設定すると、スレッドプールスレッドのみがリソースにアクセスできます。初期カウントと最大カウントの両方を2に設定した場合にのみ、2つのスレッドがリソースに同時にアクセスできます。それで、私は最初のカウントの重要性について本当に混乱していますか?

SemaphoreSlim semaphoreSlim = new SemaphoreSlim(0, 2); //all threadpool threads wait
SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 2);//only one thread has access to the resource at a time
SemaphoreSlim semaphoreSlim = new SemaphoreSlim(2, 2);//two threadpool threads can access the resource concurrently

7
どうしてSVGregの答えを受け入れなかったのですか?
ジョン

回答:


79

はい、初期数が0に設定されている場合、「CurrentCount」プロパティをインクリメントしている間、すべてのスレッドが待機します。Release()またはRelease(Int32)を使用して実行できます。

Release(...)-セマフォカウンターをインクリメントします

Wait(...)-デクリメントします

初期化で設定した最大カウントを超えてカウンター( "CurrentCount"プロパティ)をインクリメントすることはできません。

例えば:

SemaphoreSlim^ s = gcnew SemaphoreSlim(0,2); //s->CurrentCount = 0
s->Release(2); //s->CurrentCount = 2
...

s->Wait(); //Ok. s->CurrentCount = 1
...

s->Wait(); //Ok. s->CurrentCount = 0
...

s->Wait(); //Will be blocked until any of the threads calls Release()

1
あなたのコードは、コメントとしてではなく、回答でより適切に提示されます。
–ChrisF

14
コンストラクターのドキュメントでは、設定する値について常に混乱しているため、これと同じ答えに到達するのはおそらく5回目です。乾杯
BlueStrat 2016年

69

それで、私は最初のカウントの重要性について本当に混乱していますか?

ここで役立つ可能性のある重要なポイントの1つはWait、セマフォ数を減らしてRelease増やすことです。

initialCountすぐに許可されるリソースアクセスの数です。つまり、Waitセマフォがインスタンス化された直後にブロックせずに呼び出すことができる回数です。

maximumCountセマフォが取得できる最大数です。それは回数がされたReleaseと仮定すると、例外投げずに呼び出すことができますinitialCountカウントがゼロでした。initialCountがと同じ値に設定されている場合、セマフォがインスタンス化された直後にmaximumCount呼び出すReleaseと、例外がスローされます。


20
これはとても役に立ちます!initialCountは、すぐに使用できるリソースの数ではなく、最初のBLOCKEDリソースの数であるため、セマフォについては逆に考えていました。ありがとうございました。
フィリップテン2014年

5
@PhilipTennは、私は同意-ドキュメントは、この点に明確ではありません
BlueStrat

私は同意しました、彼らはその変数名を変更するか、ドキュメントを更新する必要があります
IronHide 2017

@Sandboxは、initialCountパラメータの意味を実際に説明しているため、この回答IMOを受け入れる必要があります。
のMichałTurczyn

8

一度にいくつのスレッドがリソースにアクセスできるようにしたいですか?初期カウントをその数に設定します。その数がプログラムの存続期間を通じて決して増加しない場合は、最大数もその数に設定してください。そうすれば、リソースの解放方法にプログラミングエラーが発生した場合、プログラムがクラッシュして通知されます。

(2つのコンストラクターがあります。1つは初期値のみを取得し、もう1つは最大カウントを追加で取得します。適切な方を使用してください。)


1

このように、現在のスレッドがセマフォを作成するときに、最初からいくつかのリソースを要求する可能性があります。


つまり、2つのワーカースレッドがリソースにアクセスする場合、初期カウントを変更する必要がありますか?
サンドボックス2011年

いいえ。カウントを要求するのは現在のスレッドです。現在のスレッドがアクセスパス0を​​要求しないようにするか、1つのパラメーターでオーバーロードを使用する場合。
エルノ2011年

1

しばらくの間スレッドがリソースにアクセスしないようにしたい場合は、初期カウントを0として渡し、セマフォを作成した直後にすべてのスレッドへのアクセスを許可したい場合は、最大カウントに等しい初期カウントの値を渡します。 。例えば:

hSemaphore = CreateSemaphoreA(NULL, 0, MAX_COUNT, NULL) ;

//Do something here
//No threads can access your resource

ReleaseSemaphore(hSemaphore, MAX_COUNT, 0) ;

//All threads can access the resource now

MSDNドキュメントで引用されているように-「ReleaseSemaphoreのもう1つの使用法は、アプリケーションの初期化中です。アプリケーションは、初期カウントがゼロのセマフォを作成できます。これにより、セマフォの状態がシグナルなしに設定され、すべてのスレッドが保護されたリソースにアクセスできなくなります。初期化が完了すると、ReleaseSemaphoreを使用してカウントを最大値まで増やし、保護されたリソースへの通常のアクセスを許可します。」


申し訳ありませんが、疑問を解消することはできますが、C ++での例を示しました。
Abhineet 2012

0

セマフォは、リソースのプールを保護するために使用できます。リソースプールを使用して、作成に費用かかるものを再利用しますデータベース接続など、します。

したがって、初期カウントは、あるプロセスの開始時にプール内で使用可能なリソースの数を指します。initialCountコードを読むときは、このリソースのプールを作成するためにどれだけの先行努力を払っているのかを考える必要があります。

初期カウントの重要性について本当に混乱していますか?

Initial count = Upfront cost

そのため、アプリケーションの使用プロファイルによっては、この値がアプリケーションのパフォーマンスに劇的な影響を与える可能性があります。それはただの恣意的な数ではありません。

作成するもの、作成するのにかかる費用、すぐに必要な数について慎重に検討する必要があります。このパラメーターの最適値を文字通りグラフ化できる必要があり、プロセスのパフォーマンスを実行時に適応できるように、パラメーターを構成可能にすることを検討する必要があります。


-1

MSDNは、備考セクションの下でそれを説明します:

initialCountがmaximumCountより小さい場合、効果は、現在のスレッドがWaitOne(maximumCountからinitialCountを引いた回数)回呼び出した場合と同じです。セマフォを作成するスレッドのエントリを予約したくない場合は、maximumCountとinitialCountに同じ数を使用します。

したがって、初期カウントが0で最大が2の場合、WaitOneがメインスレッドによって2回呼び出されたため、容量に達し(現在、セマフォカウントは0)、スレッドはセマフォに入ることができません。同様に、初期カウントが1で、最大が2の場合、WaitOnceが1回呼び出され、再び容量​​に達する前に1つのスレッドのみが入ることができます。

初期カウントに0が使用されている場合は、いつでもRelease(2)を呼び出して、セマフォカウントを最大に増やし、最大数のスレッドがリソースを取得できるようにすることができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.