Concurrency control is vital in multithreaded programming to ensure that shared resources are not overwhelmed by simultaneous accesses. In C#, the Semaphore class provides a robust mechanism for managing concurrent access to a resource. This article explains how to use semaphores in C#, illustrates their use with examples, and compares scenarios with and without semaphores to highlight their benefits.
What is a Semaphore?
A semaphore is a synchronization primitive that controls access to a resource by multiple threads. It maintains a count of available resources, allowing a specified number of threads to access the resource concurrently. When the count reaches zero, additional threads are blocked until the resource is released by another thread.
Example Without Semaphore
In this example, multiple threads access a shared resource without any limitation, which can lead to resource contention.
using System;
using System.Threading;
class Program
{
static void Main()
{
for (int i = 1; i <= 5; i++)
{
Thread t = new Thread(AccessResource);
t.Name = "Thread " + i;
t.Start();
}
Console.ReadLine();
}
private static void AccessResource()
{
Console.WriteLine("{0} is accessing the resource.", Thread.CurrentThread.Name);
// Simulate some work
Thread.Sleep(2000);
Console.WriteLine("{0} is done accessing the resource.", Thread.CurrentThread.Name);
}
}
Example With Semaphore
This example demonstrates the use of a semaphore to limit concurrent access to a shared resource.
using System;
using System.Threading;
class Program
{
private static Semaphore semaphore = new Semaphore(2, 2);
static void Main()
{
for (int i = 1; i <= 5; i++)
{
Thread t = new Thread(AccessResource);
t.Name = "Thread " + i;
t.Start();
}
Console.ReadLine();
}
private static void AccessResource()
{
Console.WriteLine("{0} is waiting to enter the semaphore.", Thread.CurrentThread.Name);
semaphore.WaitOne(); // Wait until the semaphore is available
Console.WriteLine("{0} has entered the semaphore.", Thread.CurrentThread.Name);
// Simulate some work
Thread.Sleep(2000);
Console.WriteLine("{0} is leaving the semaphore.", Thread.CurrentThread.Name);
semaphore.Release(); // Release the semaphore
}
}

Join the conversation! Your thoughts help the community grow.