System.Threading.Semaphore Class
Represents a System.Threading.WaitHandle that restricts the number of threads that can access a resource or pool of resources simultaneously.
Assembly: System.Threading.dll
Syntax
public sealed class Semaphore : System.Threading.WaitHandle
Remarks
A semaphore is a synchronization primitive that allows a specified number of threads to access a shared resource. It maintains a count. Each thread that enters the semaphore decrements the count. When the count reaches zero, subsequent threads attempting to enter the semaphore are blocked until the count becomes greater than zero. A thread that exits the semaphore increments the count.
The Semaphore
class is useful for controlling access to a limited number of resources, such as database connections or memory buffers. It provides a mechanism to prevent too many threads from consuming these resources concurrently, which could lead to performance degradation or errors.
For scenarios requiring a lighter-weight semaphore, consider using System.Threading.SemaphoreSlim
, which is optimized for single-process synchronization and does not involve the overhead of operating system semaphores.
Constructors
Constructor | Description |
---|---|
Semaphore(int initialCount)
|
Initializes a new instance of the Semaphore class with the specified initial count. The initial count specifies the number of threads that can enter the semaphore without blocking. |
Semaphore(int initialCount, int maximumCount)
|
Initializes a new instance of the Semaphore class with the specified initial and maximum counts. |
Semaphore(int initialCount, int maximumCount, string name)
|
Initializes a new instance of the Semaphore class with the specified initial and maximum counts and a name. This constructor is primarily used for creating named semaphores that can be accessed across processes. |
Semaphore(int initialCount, int maximumCount, string name, out bool createdNew)
|
Initializes a new instance of the Semaphore class with the specified initial and maximum counts and a name, and indicates whether a new semaphore was created. |
Methods
Method | Description |
---|---|
WaitOne()
|
Waits until the current thread can enter the semaphore. The method returns true if the thread successfully entered the semaphore, and false if the wait timed out. |
WaitOne(int millisecondsTimeout)
|
Waits until the current thread can enter the semaphore, using a specified time-out interval. |
WaitOne(TimeSpan timeout)
|
Waits until the current thread can enter the semaphore, using a specified time-out interval. |
WaitAny(WaitHandle[] waitHandles)
|
Waits for any one of the elements in the specified array to receive a signal. |
WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout)
|
Waits for any one of the elements in the specified array to receive a signal, using a specified time-out interval. |
WaitAny(WaitHandle[] waitHandles, TimeSpan timeout)
|
Waits for any one of the elements in the specified array to receive a signal, using a specified time-out interval. |
Release()
|
Increments the semaphore's count. This allows another thread to enter the semaphore. |
Release(int releaseCount)
|
Increments the semaphore's count by the specified value. This allows up to releaseCount threads to enter the semaphore. |
Dispose()
|
Releases all resources used by the current Semaphore instance. |
Methods Inherited from System.Threading.WaitHandle
The Semaphore class inherits methods like Close()
, Handle
, and others from the System.Threading.WaitHandle base class.
Example Usage
Release()
for every successful call to WaitOne()
to prevent deadlocks and semaphore starvation. Using a try-finally
block or a using
statement with the semaphore can help manage this reliably.
using System;
using System.Threading;
public class SemaphoreExample
{
// A semaphore that allows at most 3 threads to access a resource concurrently.
private static Semaphore _pool;
public static void Main(string[] args)
{
// Initialize the semaphore with a maximum count of 3.
_pool = new Semaphore(3, 3);
Console.WriteLine("Starting worker threads...");
// Create and start 10 worker threads.
for (int i = 1; i <= 10; i++)
{
Thread worker = new Thread(new ParameterizedThreadStart(Worker));
worker.Start(i);
}
Console.WriteLine("All worker threads started.");
Console.ReadKey(); // Keep the console open
}
private static void Worker(object id)
{
Console.WriteLine($"Thread {id}: Waiting to enter the pool...");
// Wait until a slot is available.
_pool.WaitOne();
Console.WriteLine($"Thread {id}: Entered the pool. Working...");
// Simulate some work.
Thread.Sleep(2000);
Console.WriteLine($"Thread {id}: Exiting the pool.");
// Release the semaphore slot.
_pool.Release();
}
}