Sure, here is an example of using Semaphores in C#:
csharpusing System;
using System.Threading;
class SemaphoreExample
{
static SemaphoreSlim semaphore = new SemaphoreSlim(3); // Initialize semaphore with 3 slots
static void Main()
{
// Create 5 threads
for (int i = 1; i <= 5; i++)
{
Thread t = new Thread(Enter);
t.Name = $"Thread {i}";
t.Start();
}
}
static void Enter()
{
Console.WriteLine($"{Thread.CurrentThread.Name} is trying to enter");
semaphore.Wait(); // Wait until there is an available slot
Console.WriteLine($"{Thread.CurrentThread.Name} has entered");
Thread.Sleep(1000); // Do some work
Console.WriteLine($"{Thread.CurrentThread.Name} is leaving");
semaphore.Release(); // Release the slot
}
}
In this example, we create a SemaphoreSlim
object with 3 slots, and then we create 5 threads that will try to enter the semaphore. Each thread tries to enter by calling Wait()
on the semaphore, which will block until there is an available slot. Once a thread enters, it does some work and then releases the slot by calling Release()
on the semaphore.
Sure, I'd be happy to explain each line of the code example:
csharpusing System;
using System.Threading;
These are the using
directives that allow us to use the System
namespace and the System.Threading
namespace in our code. The System
namespace contains fundamental classes and base classes that define commonly-used value and reference data types, events and event handlers, interfaces, attributes, and processing exceptions. The System.Threading
namespace contains classes and interfaces that enable multithreaded programming.
csharpclass SemaphoreExample
{
static SemaphoreSlim semaphore = new SemaphoreSlim(3); // Initialize semaphore with 3 slots
static void Main()
{
// Create 5 threads
for (int i = 1; i <= 5; i++)
{
Thread t = new Thread(Enter);
t.Name = $"Thread {i}";
t.Start();
}
}
We define a class SemaphoreExample
and declare a SemaphoreSlim
object called semaphore
. We pass the integer value 3 to the SemaphoreSlim
constructor to initialize the semaphore with 3 slots.
In the Main
method, we create 5 threads and start them. Each thread is created by calling the Thread
constructor with the method name Enter
as the parameter. We set the name of each thread to Thread i
using the Name
property and then start the thread by calling the Start()
method.
csharp static void Enter()
{
Console.WriteLine($"{Thread.CurrentThread.Name} is trying to enter");
semaphore.Wait(); // Wait until there is an available slot
Console.WriteLine($"{Thread.CurrentThread.Name} has entered");
Thread.Sleep(1000); // Do some work
Console.WriteLine($"{Thread.CurrentThread.Name} is leaving");
semaphore.Release(); // Release the slot
}
The Enter
method is the method that will be called by each thread. First, it prints a message indicating that it is trying to enter the semaphore. It then calls the Wait
method on the semaphore
, which blocks until there is an available slot. Once a slot is available, the thread enters the semaphore, prints a message indicating that it has entered, and then performs some work, represented by the Thread.Sleep(1000)
call. After the work is done, the thread prints a message indicating that it is leaving the semaphore and then releases the slot by calling the Release
method on the semaphore
.
I hope this explanation helps you understand the code example better!