Semaphore クラス
アセンブリ: System (system.dll 内)
構文
解説
メモ |
---|
このクラスに適用される HostProtectionAttribute 属性の Resources プロパティの値は、Synchronization または ExternalThreading です。HostProtectionAttribute は、デスクトップ アプリケーション (一般的には、アイコンをダブルクリック、コマンドを入力、またはブラウザに URL を入力して起動するアプリケーション) には影響しません。詳細については、HostProtectionAttribute クラスのトピックまたは「SQL Server プログラミングとホスト保護属性」を参照してください。 |
リソースのプールへのアクセスを制御するには、Semaphore クラスを使用します。スレッドは、WaitHandle クラスから継承された WaitOne メソッドを呼び出すことによってセマフォに入り、Release メソッドを呼び出すことによってセマフォを解放します。
セマフォのカウントは、1 つのスレッドがセマフォに入るたびにデクリメントされ、1 つのスレッドがセマフォを解放するたびにインクリメントされます。カウントが 0 になると、それ以降の要求は他のスレッドがセマフォを解放するまでブロックされます。すべてのスレッドがセマフォを解放すると、カウントはセマフォの作成時に設定された最大値になります。
ブロックされたスレッドがセマフォに入る際、FIFO または LIFO のような保証された順序はありません。
WaitOne メソッドを繰り返し呼び出すと、1 つのスレッドが複数回セマフォに入ることができます。このようなエントリの一部またはすべてを解放するには、スレッドでパラメータなしの Release メソッド オーバーロードを複数回呼び出すか、または、解放するエントリの数を指定する Release(Int32) メソッド オーバーロードを呼び出します。
Semaphore クラスは、WaitOne または Release の呼び出しにスレッドの ID を適用しません。プログラマは、スレッドがセマフォを必要な回数以上、解放しないように注意する必要があります。たとえば、あるセマフォのカウントの最大値が 2 で、スレッド A およびスレッド B が両方ともこのセマフォに入ったとします。スレッド B のプログラミング エラーによって Release が 2 回呼び出された場合、呼び出しは 2 回とも成功します。セマフォはカウントの最大値に達し、最終的にスレッド A が Release を呼び出すと、SemaphoreFullException がスローされます。
セマフォには、ローカル セマフォと名前付きシステム セマフォの 2 種類があります。名前を受け入れるコンストラクタを使用して Semaphore オブジェクトを作成した場合、オブジェクトはその名前のオペレーティング システム セマフォに関連付けられます。名前付きシステム セマフォはオペレーティング システム全体から参照でき、プロセスの動作を同期するために使用できます。同じ名前付きシステム セマフォを表す複数の Semaphore オブジェクトを作成できます。また、OpenExisting メソッドを使用すると、既存の名前付きシステム セマフォを開くことができます。
ローカル セマフォは該当するプロセス内のみに存在します。これは、ローカル Semaphore オブジェクトへの参照を持つプロセス内のすべてのスレッドで使用できます。各 Semaphore オブジェクトは個別のローカル セマフォです。
カウントの最大値が 3 で初期カウントが 0 のセマフォを作成するコード例を次に示します。この例では 5 つのスレッドが開始され、ブロックされてセマフォを待機します。メイン スレッドが Release(Int32) メソッド オーバーロードを使用してセマフォのカウントを最大値まで増加させ、3 つのスレッドがセマフォに入ることができるようにします。各スレッドは、動作をシミュレートするために System.Threading.Thread.Sleep メソッドを使用して 1 秒間待機し、その後 Release メソッド オーバーロードを呼び出してセマフォを解放します。セマフォが解放されるたびに、前のセマフォのカウントが表示されます。コンソール メッセージは、セマフォの使用状況を追跡します。出力を読み取りやすくするために、シミュレートされた動作間隔がスレッドごとに若干増加します。
Imports System Imports System.Threading Public Class Example ' A semaphore that simulates a limited resource pool. ' Private Shared _pool As Semaphore ' A padding interval to make the output more orderly. Private Shared _padding As Integer <MTAThread> _ Public Shared Sub Main() ' Create a semaphore that can satisfy up to three ' concurrent requests. Use an initial count of zero, ' so that the entire semaphore count is initially ' owned by the main program thread. ' _pool = New Semaphore(0, 3) ' Create and start five numbered threads. ' For i As Integer = 1 To 5 Dim t As New Thread(New ParameterizedThreadStart(AddressOf Worker)) 'Dim t As New Thread(AddressOf Worker) ' Start the thread, passing the number. ' t.Start(i) Next i ' Wait for half a second, to allow all the ' threads to start and to block on the semaphore. ' Thread.Sleep(500) ' The main thread starts out holding the entire ' semaphore count. Calling Release(3) brings the ' semaphore count back to its maximum value, and ' allows the waiting threads to enter the semaphore, ' up to three at a time. ' Console.WriteLine("Main thread calls Release(3).") _pool.Release(3) Console.WriteLine("Main thread exits.") End Sub Private Shared Sub Worker(ByVal num As Object) ' Each worker thread begins by requesting the ' semaphore. Console.WriteLine("Thread {0} begins " _ & "and waits for the semaphore.", num) _pool.WaitOne() ' A padding interval to make the output more orderly. Dim padding As Integer = Interlocked.Add(_padding, 100) Console.WriteLine("Thread {0} enters the semaphore.", num) ' The thread's "work" consists of sleeping for ' about a second. Each thread "works" a little ' longer, just to make the output more orderly. ' Thread.Sleep(1000 + padding) Console.WriteLine("Thread {0} releases the semaphore.", num) Console.WriteLine("Thread {0} previous semaphore count: {1}", _ num, _ _pool.Release()) End Sub End Class
using System; using System.Threading; public class Example { // A semaphore that simulates a limited resource pool. // private static Semaphore _pool; // A padding interval to make the output more orderly. private static int _padding; public static void Main() { // Create a semaphore that can satisfy up to three // concurrent requests. Use an initial count of zero, // so that the entire semaphore count is initially // owned by the main program thread. // _pool = new Semaphore(0, 3); // Create and start five numbered threads. // for(int i = 1; i <= 5; i++) { Thread t = new Thread(new ParameterizedThreadStart(Worker)); // Start the thread, passing the number. // t.Start(i); } // Wait for half a second, to allow all the // threads to start and to block on the semaphore. // Thread.Sleep(500); // The main thread starts out holding the entire // semaphore count. Calling Release(3) brings the // semaphore count back to its maximum value, and // allows the waiting threads to enter the semaphore, // up to three at a time. // Console.WriteLine("Main thread calls Release(3)."); _pool.Release(3); Console.WriteLine("Main thread exits."); } private static void Worker(object num) { // Each worker thread begins by requesting the // semaphore. Console.WriteLine("Thread {0} begins " + "and waits for the semaphore.", num); _pool.WaitOne(); // A padding interval to make the output more orderly. int padding = Interlocked.Add(ref _padding, 100); Console.WriteLine("Thread {0} enters the semaphore.", num); // The thread's "work" consists of sleeping for // about a second. Each thread "works" a little // longer, just to make the output more orderly. // Thread.Sleep(1000 + padding); Console.WriteLine("Thread {0} releases the semaphore.", num); Console.WriteLine("Thread {0} previous semaphore count: {1}", num, _pool.Release()); } }
#using <System.dll> using namespace System; using namespace System::Threading; public ref class Example { private: // A semaphore that simulates a limited resource pool. // static Semaphore^ _pool; // A padding interval to make the output more orderly. static int _padding; public: static void Main() { // Create a semaphore that can satisfy up to three // concurrent requests. Use an initial count of zero, // so that the entire semaphore count is initially // owned by the main program thread. // _pool = gcnew Semaphore( 0,3 ); // Create and start five numbered threads. // for ( int i = 1; i <= 5; i++ ) { Thread^ t = gcnew Thread( gcnew ParameterizedThreadStart( Worker ) ); // Start the thread, passing the number. // t->Start( i ); } // Wait for half a second, to allow all the // threads to start and to block on the semaphore. // Thread::Sleep( 500 ); // The main thread starts out holding the entire // semaphore count. Calling Release(3) brings the // semaphore count back to its maximum value, and // allows the waiting threads to enter the semaphore, // up to three at a time. // Console::WriteLine( L"Main thread calls Release(3)." ); _pool->Release( 3 ); Console::WriteLine( L"Main thread exits." ); } private: static void Worker( Object^ num ) { // Each worker thread begins by requesting the // semaphore. Console::WriteLine( L"Thread {0} begins and waits for the semaphore.", num ); _pool->WaitOne(); // A padding interval to make the output more orderly. int padding = Interlocked::Add( _padding, 100 ); Console::WriteLine( L"Thread {0} enters the semaphore.", num ); // The thread's "work" consists of sleeping for // about a second. Each thread "works" a little // longer, just to make the output more orderly. // Thread::Sleep( 1000 + padding ); Console::WriteLine( L"Thread {0} releases the semaphore.", num ); Console::WriteLine( L"Thread {0} previous semaphore count: {1}", num, _pool->Release() ); } };
import System.*; import System.Threading.*; public class Example { // A semaphore that simulates a limited resource pool. // private static Semaphore _pool; // A padding interval to make the output more orderly. private static int _padding; public static void main(String[] args) { // Create a semaphore that can satisfy up to three // concurrent requests. Use an initial count of zero, // so that the entire semaphore count is initially // owned by the main program thread. // _pool = new Semaphore(0, 3); // Create and start five numbered threads. // for (int i = 1; i <= 5; i++) { System.Threading.Thread t = new System.Threading.Thread(new ParameterizedThreadStart(Worker)); // Start the thread, passing the number. // t.Start((Int32)i); } // Wait for half a second, to allow all the // threads to start and to block on the semaphore. // System.Threading.Thread.Sleep(500); // The main thread starts out holding the entire // semaphore count. Calling Release(3) brings the // semaphore count back to its maximum value, and // allows the waiting threads to enter the semaphore, // up to three at a time. // Console.WriteLine("main thread calls Release(3)."); _pool.Release(3); Console.WriteLine("main thread exits."); } //main private static void Worker(Object num) { // Each worker thread begins by requesting the // semaphore. Console.WriteLine("Thread {0} begins " + "and waits for the semaphore.", num); _pool.WaitOne(); // A padding interval to make the output more orderly. int padding = Interlocked.Add(_padding, 100); Console.WriteLine("Thread {0} enters the semaphore.", num); // The thread's "work" consists of sleeping for // about a second. Each thread "works" a little // longer, just to make the output more orderly. // System.Threading.Thread.Sleep(1000 + padding); Console.WriteLine("Thread {0} releases the semaphore.", num); Console.WriteLine("Thread {0} previous semaphore count: {1}", num, (Int32)_pool.Release()); } //Worker } //Example
System.MarshalByRefObject
System.Threading.WaitHandle
System.Threading.Semaphore
プラットフォーム
Windows 98, Windows 2000 SP4, Windows Millennium Edition, Windows Server 2003, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP SP2, Windows XP Starter Edition
開発プラットフォームの中には、.NET Framework によってサポートされていないバージョンがあります。サポートされているバージョンについては、「システム要件」を参照してください。
参照
- Semaphore クラスのページへのリンク