Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Semaphore in C#
A Semaphore in C# is a synchronization primitive that controls access to a pool of resources by allowing a specified number of threads to enter a critical section simultaneously. It maintains a count of available permits and blocks threads when the limit is reached.
The System.Threading.Semaphore class provides all the methods and properties needed to implement semaphore functionality in multithreaded applications.
Syntax
The basic syntax for creating a semaphore −
Semaphore semaphore = new Semaphore(initialCount, maximumCount);
To acquire and release the semaphore −
semaphore.WaitOne(); // Acquire the semaphore // Critical section code semaphore.Release(); // Release the semaphore
Parameters
initialCount − The initial number of requests for the semaphore that can be granted concurrently.
maximumCount − The maximum number of requests for the semaphore that can be granted concurrently.
name (optional) − The name of a system semaphore object for named semaphores.
Semaphore Constructors
| Constructor | Description |
|---|---|
| Semaphore(Int32, Int32) | Initializes a new instance specifying initial and maximum concurrent entries. |
| Semaphore(Int32, Int32, String) | Initializes a new instance with optional name for system semaphore object. |
| Semaphore(Int32, Int32, String, Boolean) | Initializes a new instance with name and variable indicating if new system semaphore was created. |
Using Semaphore for Thread Synchronization
Example
using System;
using System.Threading;
class Demo {
static Thread[] threads = new Thread[5];
static Semaphore semaphore = new Semaphore(2, 2);
static void DoSomething() {
Console.WriteLine("{0} = waiting", Thread.CurrentThread.Name);
semaphore.WaitOne();
Console.WriteLine("{0} begins!", Thread.CurrentThread.Name);
Thread.Sleep(1000);
Console.WriteLine("{0} releasing...", Thread.CurrentThread.Name);
semaphore.Release();
}
static void Main(string[] args) {
for (int j = 0; j < 5; j++) {
threads[j] = new Thread(DoSomething);
threads[j].Name = "Thread-" + j;
threads[j].Start();
}
foreach (Thread t in threads) {
t.Join();
}
Console.WriteLine("All threads completed");
}
}
The output of the above code is −
Thread-0 = waiting Thread-1 = waiting Thread-2 = waiting Thread-3 = waiting Thread-4 = waiting Thread-0 begins! Thread-1 begins! Thread-0 releasing... Thread-1 releasing... Thread-2 begins! Thread-3 begins! Thread-2 releasing... Thread-3 releasing... Thread-4 begins! Thread-4 releasing... All threads completed
Semaphore with Different Count Values
Example
using System;
using System.Threading;
class ResourcePool {
static Semaphore semaphore = new Semaphore(1, 3); // Start with 1, max 3
static void AccessResource(object id) {
Console.WriteLine("Thread {0} requesting access", id);
semaphore.WaitOne();
Console.WriteLine("Thread {0} has entered the pool", id);
Thread.Sleep(2000);
Console.WriteLine("Thread {0} is leaving the pool", id);
semaphore.Release();
}
static void Main() {
for (int i = 1; i <= 4; i++) {
Thread t = new Thread(AccessResource);
t.Start(i);
}
Thread.Sleep(8000);
Console.WriteLine("Main thread finished");
}
}
The output of the above code is −
Thread 1 requesting access Thread 2 requesting access Thread 3 requesting access Thread 4 requesting access Thread 1 has entered the pool Thread 1 is leaving the pool Thread 2 has entered the pool Thread 2 is leaving the pool Thread 3 has entered the pool Thread 3 is leaving the pool Thread 4 has entered the pool Thread 4 is leaving the pool Main thread finished
How It Works
A semaphore maintains an internal counter that gets decremented when WaitOne() is called and incremented when Release() is called. When the counter reaches zero, subsequent calls to WaitOne() block until another thread calls Release().
Conclusion
Semaphores in C# provide an effective way to control concurrent access to shared resources by limiting the number of threads that can enter a critical section simultaneously. They are essential for managing thread pools and preventing resource contention in multithreaded applications.
