web-dev-qa-db-ja.com

セマフォの実用的な使い方は何ですか?

非バイナリのもの..
ミューテックスの代わりにセマフォを使用する必要がある問題に遭遇したことはありません。それで、これはほとんど理論的な構成ですか、それともOfficeのような実際のソフトウェアですか?Firefoxにはそれを使用する場所がありますか?もしそうなら、セマフォの一般的な使用パターンは何ですか?

18
NoSenseEtAl

セマフォとは何かをすでにご存知だと思いますが、「実際のソフトウェア」でどのように使用されているのか疑問に思っているだけです。

「Officeのような本当のソフトウェア、Firefoxにはそれを使用する場所がありますか?」

はい、「実際のソフトウェア」はセマフォを頻繁に使用します。これは理論上のものだけではありません。 クロムソース、Windowsセマフォ処理コード および 仮想ボックス で使用されるのと同じコード。

「セマフォの実際の使用法は何ですか」/「セマフォの一般的な使用パターンは何ですか?」

これらは、生産者/消費者同期の問題により適しています。プロデューサーとコンシューマーの数両方> 1である状況。

セマフォの典型的な使用法のFuhrmanatorの 参照 は良いものです。

4
Edgar Carvalho

非バイナリセマフォは、リソース割り当てで使用されます。セマフォは、特定のリソースの数のカウントを保持する場合があります。

Webブラウザーが使用するような接続のプールがある場合、個々のスレッドは、セマフォが接続を取得するのを待ってプールのメンバーを予約し、接続を使用してから、セマフォを解放することによって接続を解放します。

カウンターを作成し、カウンターの周囲に相互排除領域を確立することで、セマフォをエミュレートできます。ただし、上記のようなリソースを待機するには、2レベルのミューテックスが必要であり、セマフォを使用するほどエレガントではありません。

17
Bob Dalgleish

セマフォは数えることができます。カウントは基本的にスレッドセーフではなく、プロセッサでの読み取り-変更-書き込み操作であるため、atomicではありません。安全にカウントするために使用できるプリミティブは少なく、Interlocked.Increment()はアトミックです。しかし、アトミック性はかなり弱いスレッドプリミティブであり、多くの場合、カウントが臨界値にあるときにコードをブロックする必要があります。

0が「クリティカル」であるため、すべてのリソースが使用されています。標準的な例は、スレッドを実行するためにプロセッサコアをカウントダウンすることです。スレッドをすべて使用したら、そのうちの1つが完了し、プロセッサコアが不要になるまで、別のスレッドを開始しないでください。それが得るのと同じくらい基本的です。

バイナリセマフォは、スレッド化に関する文献によく登場します。標準的な教科書のエントリであり、エドガー・ダイクストラと呼ばれる仲間のオランダ人と密接に結びついています。コンピュータサイエンスのパイオニアであり、1960年代に、プロセッサに複数のプログラムを実行させるために何をするかについて最初に考え始めました。彼のPとVの注釈は、私のようなオランダ語を話す人にのみ意味があります。 ParkeerとVrijは、車をどこかに配置しようとするときに使用する用語です:)これは、ミューテックスやモニターなど、さまざまな種類のスレッドプリミティブを使用することを誰もが考え始めるずっと前のことです。セマフォのサポートのみを必要とするプリミティブ。バイナリセマフォを取得したら、他のすべてを実行します。基本的な機能の上に抽象化を構築し、ソフトウェアで構成が機能する方法。

セマフォをミューテックスやモニターのような他のプリミティブとはかなり異なるものにしていることの1つは、lockがそうではないということです。スレッドアフィニティがありません。スレッド化されたコードを書くとき、それはかなり大きな問題です。実装しようとする通常コントラクトは、同時に1つのスレッドだけがリソースにアクセスできるということです。他のすべての.NET同期オブジェクトは再入可能であり、同じスレッドで複数回ロックを取得してデッドロックすることはできません。彼らはとてもフレンドリーで、あなたがロックを取得するときに単にカウンターをインクリメントします。そして、リリースしたらもう一度カウントダウンします。そして、カウントが0に達したときにのみロックをあきらめます。セマフォはそのようにはまったく機能しません。どのスレッドがそれを取得したかに関係なく、取得したときにカウントされます。先に引用したスレッドリソースのカウントダウンの例のように、本当に重要な場合もあります。

これは本当にに役立ちます。あまり一般的ではありません。モニターはスイスのスレッディングのアーミーナイフであり、それが独自のキーワードを持っている理由です。 C#のlockキーワード、VB.NETのSyncLock

10
Hans Passant

Doug Schmidtの引用 http://www.cs.wustl.edu/~schmidt/win32-cv-1.html セクション2.2:

セマフォのカウントは、制御の複数のスレッドをシリアル化または調整するために一般的に使用される同期メカニズムです。概念的には、カウントセマフォは非負の整数であり、アトミックにインクリメントおよびデクリメントできます。スレッドが値が0に等しいセマフォをデクリメントしようとすると、このスレッドは中断され、別のスレッドがセマフォカウントを0より大きくインクリメントするのを待ちます。

カウントセマフォは、プロセス内の複数のスレッドによって共有されるオブジェクトの状態の変化を追跡するためによく使用されます。たとえば、特定のイベントの発生を記録できます。条件変数とは異なり、セマフォは状態を維持します。したがって、イベントが過去に発生した場合でも、スレッドはこの状態に基づいて決定を下すことができます。

パターンに関しては、 http://www.freertos.org/Real-time-embedded-RTOS-Counting-Semaphores.html のように2つあります。

セマフォのカウントは通常、次の2つの目的で使用されます。

  1. イベントのカウント。この使用シナリオでは、イベントハンドラーはイベントが発生するたびにセマフォを「提供」し(セマフォカウント値をインクリメント)、ハンドラータスクはイベントを処理するたびにセマフォを取得します(セマフォカウント値をデクリメントします)。したがって、カウント値は、発生したイベントの数と処理された数の差です。この場合、セマフォの作成時にカウント値がゼロであることが望ましいです。

  2. 資源管理。この使用シナリオでは、カウント値は使用可能なリソースの数を示します。リソースの制御を取得するには、タスクは最初にセマフォを取得する必要があります-セマフォカウント値をデクリメントします。カウント値がゼロに達すると、空きリソースはありません。タスクがリソースで終了すると、タスクはセマフォを「返します」-セマフォカウント値をインクリメントします。この場合、セマフォの作成時にカウント値が最大カウント値と等しくなることが望ましいです。

5
Fuhrmanator

考えられる実際的な例は、固定スレッドプールです。すべてのシステムリソースを無駄にしたくないので、特定の時間に特定の数のスレッドのみを実行できます。残りのすべてのスレッドはキューで待機します。

さて、たとえばJavaスレッドプールがセマフォのような裸のリソースを使用して実装されているかどうかは疑わしいですが、どの同期構造が使用されても、理論的には同等です。 Javaスレッドプール(および固定スレッドプール)の詳細については、こちらをご覧ください: http://docs.Oracle.com/javase/tutorial/essential/concurrency/pools.html

4
Luke

プロダクション環境でセマフォを数回使用しました。実行するタスクのリストを取得するWindowsサービスを実行します。これらのタスクはすべて並行して実行できます。そのため、最初はすべてを.netスレッドプールにドロップし、実行するように設定しました。

しばらくすると、問題が発生しました。並行して実行された作業もスレッドプールを使用していました。したがって、スレッドプールで開始したタスクが多すぎると、プール全体が消費され、キューに入れられたタスクがスレッドプールにスロットを取得するのを待ちます。

リークのある解決策は、タスクが実行を続けると、タスクがインクリメントおよびデクリメントする共有カウンターを保持することでした。それはしばらくの間機能しましたが、最終的にサービスは何もしなくなりました。競合状態が繰り返されると、何も実行されていなくても、スレッドプールで許可されているすべてのスロットが使用されたことがカウンターに示されました。

結局、セマフォが問題を解決しました。

4
Grubsnik