web-dev-qa-db-ja.com

カウントセマフォとバイナリセマフォの違い

カウントとバイナリセマフォの違いは何ですか。

私がどこかで見たことは、両方がリソースを要求したN個のプロセスを制御できることです。両方とも、フリー状態を取りました。

バイナリセマフォとカウントセマフォが保護できるリソースの数に制限はありますか?

両方とも、一度に1つのプロセスのみがリソースを使用できます...

他に違いはありますか?上記のプロパティは正しいですか?

27
Umer Farooq

実際には、アクセスしようとしているエンティティがプロセスであってもスレッドであっても、両方のタイプが共有リソースへのアクセスを同期するために使用されます。

違いは次のとおりです。

バイナリセマフォはバイナリであり、2つの値のみを持つことができます。 1つはプロセス/スレッドがクリティカルセクション(共有リソースにアクセスするコード)にあり、他は待機する必要があることを表し、もう1つはクリティカルセクションが空いていることを示します。

一方、カウントセマフォは3つ以上の値を取ります。任意の値を設定できます。それらが取る最大値Xにより、Xプロセス/スレッドは共有リソースに同時にアクセスできます。

詳細については、このリンクをご覧ください。
http://www.chibios.org/dokuwiki/doku.php?id=chibios:articles:semaphores_mutexes

[〜#〜] edit [〜#〜]
カウンティングセマフォが使用できる最大値は、同時にクリティカルセクションに許可するプロセスの数です。
繰り返しますが、特定のリソースを除外したい場合がありますが、このリソースには最大数のプロセス(Xなど)からアクセスできることがわかっているので、値Xでカウントセマフォを設定します。

これにより、Xプロセスはそのリソースに同時にアクセスできます。それでも、プロセスX + 1は、クリティカルセクションのプロセスの1つが出るまで待たなければなりません。

31
Fingolfin

並行プログラムの構築には、同期と相互排除という2つの重要な概念があります。これらの2種類のロック(セマフォは一般的に一種のロックメカニズムです)が、同期と相互排除の実現にどのように役立つかを見ていきます。

セマフォには、カウンターと、特定のリソースへのアクセスを待機しているタスクのリストの2つの部分があります。セマフォは2つの操作を実行します。待機(P)[これはロックの取得に似ています]とリリース(V)[ロックの解放に似ています]-これらはセマフォで実行できる2つの操作です。バイナリセマフォでは、カウンタは論理的に0から1の間に入ります。これは、オープン/クローズの2つの値を持つロックに似ていると考えることができます。カウントセマフォには、カウント用の複数の値があります。

理解することが重要なのは、セマフォカウンターがブロックする必要のないタスクの数を追跡していることです。つまり、タスクを進行させることができます。タスクはブロックし、カウンターがゼロの場合にのみセマフォのリストに自分自身を追加します。したがって、タスクは、進行できない場合はP()ルーチンのリストに追加され、V()ルーチンを使用して「解放」されます。

バイナリセマフォを使用して、同期と相互排除を解決する方法を確認するのは非常に明白です。これらは本質的にロックです。

例同期:

thread A{
semaphore &s; //locks/semaphores are passed by reference! think about why this is so.
A(semaphore &s): s(s){} //constructor
foo(){
...
s.P();
;// some block of code B2
...
}

//thread B{
semaphore &s;
B(semaphore &s): s(s){} //constructor
foo(){
...
...
// some block of code B1
s.V();
..
}

main(){
semaphore s(0); // we start the semaphore at 0 (closed)
A a(s);
B b(s);
}

上記の例では、B2は実行できますafter B1は実行を終了しました。スレッドAが最初に実行されるとしましょう-sem.P()に到達し、カウンターが0(クローズ)であるため待機します。スレッドBが登場し、B1を終了し、スレッドAを解放します。これにより、B2が完了します。したがって、同期を実現します。

次に、バイナリセマフォを使用した相互排除について見てみましょう。

thread mutual_ex{
semaphore &s;
mutual_ex(semaphore &s): s(s){} //constructor
foo(){
...
s.P();
//critical section
s.V();
...
...
s.P();
//critical section
s.V();
...

}

main(){
semaphore s(1);
mutual_ex m1(s);
mutual_ex m2(s);
}

相互排他も非常に簡単です-m1とm2は同時にクリティカルセクションに入ることはできません。そのため、各スレッドは同じセマフォを使用して、その2つのクリティカルセクションを相互排除します。さて、並行性を高めることは可能ですか?クリティカルセクションに依存します。 (セマフォを使用して相互排除を実現する方法について考えてみてください。hint:必然的にoneセマフォのみを使用する必要がありますか?)

カウントセマフォ:複数の値を持つセマフォ。これが意味するものを見てみましょう-複数の値?のロック開いて、閉じて、...うーん。相互排除または同期におけるマルチステージロックの用途は何ですか?

2つの簡単な方法を見てみましょう。

カウントセマフォを使用した同期:3つのタスク(#1と2を3の後に実行したい)があるとします。どのように同期を設計しますか?

thread t1{
...
s.P();
//block of code B1

thread t2{
...
s.P();
//block of code B2

thread t3{
...
//block of code B3
s.V();
s.V();
}

そのため、セマフォが閉じて起動した場合、t1とt2がブロックされ、セマフォのリストに追加されます。その後、すべての重要なt3が登場し、ビジネスを終了し、t1とt2を解放します。どの順序で解放されますか?セマフォのリストの実装に依存します。 FIFO、特定の優先度などに基づいている可能性があります。 (:特定の順序でt1とt2を実行したい場合、およびセマフォの実装を認識していない場合は、PとVをどのように配置するかを考えてください)

検索:Vの数がPの数よりも大きい場合はどうなりますか?)

カウントセマフォを使用した相互排除:このために独自の擬似コードを作成してほしい(物事をよりよく理解できるようになります!)-しかし、基本的な概念はこれです:counter = NのカウントセマフォはNを許可しますクリティカルセクションに自由に入るためのタスク。これは、N個のタスク(または必要に応じてスレッド)がクリティカルセクションに入ることを意味しますが、N + 1番目のタスクはブロックされ(お気に入りのブロックされたタスクリストに追加されます)、誰かVがセマフォである場合にのみ許可されます少なくとも一度は。そのため、セマフォカウンターは0と1の間でスイングする代わりに0とNの間で移動し、Nタスクが自由に出入りできるようにし、誰もブロックしません!

さて、なぜあなたはそのような奇妙なロックが必要なのでしょうか?相互排除の全体のポイントは、複数の人がリソースにアクセスできないようにすることではありませんか??考えて。 (Hint ...コンピューターに常にoneドライブがあるとは限りません、あなたは...?)

考えてみると:カウントセマフォを単独で使用することで相互排除は達成されますか?リソースのインスタンスが10個あり、10個のスレッドが(カウントセマフォを介して)入って、最初のインスタンスを使用しようとするとどうなりますか?

8
aspen100

カウントとバイナリセマフォの最も基本的な違いは次のとおりです。

  1. バイナリセマフォは、バイナリ値を保持する変数であるため、バウンド待機を処理できません。 Counting semaphore変数をQueueを持つ構造体に変換したため、制限付き待機を処理できます。
  2. Strcutureの実装バイナリセマフォ:int s;

    セマフォのカウント:Struct S {int s;キューq; }

カウントセマフォを使用すると、CS(クリティカルセクション)が取得されると、もう一方のプロセスがCSを取得するのを待たなければならないため、単一のプロセスストーブではありません。各プロセスには、CSのチャンスがあります。

1
user7730503