J. Doe
J. Doe

Reputation: 1317

How does a semaphore release from another thread?

From what I know a thread can release on a semaphore without first acquiring a lock with WaitOne.

So, if we have threads A, B and C and a semaphore, A and B call WaitOne, get a lock and start doing their business.
Along comes thread C and just calls Release on the semaphore.

This should increment the semaphore's count by 1. Does this mean the semaphore will terminate either A or B or just allow a third thread to acquire a lock and have 3 threads in its pool, even if the maximum was 2?

Upvotes: 2

Views: 4042

Answers (2)

Shahar Shokrani
Shahar Shokrani

Reputation: 8762

Consider

var semaphore = new SemaphoreSlim(2);

It means that the semaphore at this moment of time has only 2 executions slots, but you have to keep in mind that it is only the initial number of executions slots (for requests to be granted concurrently).

So, if we will spawn A,B,C thread into a semaphore with 2 executions slots the first two threads will be executed and the C thread will be queued until someone else in the code will signal the semaphore it is OK to add one more execution slot.

When someone will say its OK to execute the next thread in the queue, the C will be executed regardless to the others thread.


Some technical example:

(As I saw in @dmitri-nesteruk's course)

The total number of available executions slots is being represented by CurrentCount.

Each time a thread wanted to be executed it asks the semaphore if it has an available execution slot (with CurrentCount > 0), if true - feel free to get yourself executed, if not get inside the queue.

What makes the semaphore so confusing is the fact that CurrentCount value can be either decreased or increased.

  • Its decreases by one each time the Wait() has been called by a thread, which means that there is one less available execution slot and the a thread is being executed.

  • Its increases by one (or more) each time the Release(1) has been called somewhere else in the code, which means that there is one more available execution slot so the first thread in the semaphore inside queue is being executed (it won't terminate the others).

In this example the we spawn 3 threads, but the only first two will be executed until someone will say to the semaphore that he can release another execution slot by increasing the CurrentCount with Release(1).

for (int i = 0; i < 3 ; i++)
{
    Task.Factory.StartNew(() => 
    {
        Console.WriteLine($"Spawning task: {Task.CurrentId}");
        semaphore.Wait(); //CurrentCount--
        Console.WriteLine($"Executing task: {Task.CurrentId}");
    });
}


while (semaphore.CurrentCount <= 2)
{
    Console.ReadKey();
    Console.WriteLine("Key pressed");
    semaphore.Release(1); //CurrentCount++
}

The Output:

Spawning task: A
Spawning task: B
Spawning task: C
Executing task: A
Executing task: B
.....
Key pressed
Executing task: C

Upvotes: 2

Solomon Slow
Solomon Slow

Reputation: 27115

You can think of a semaphore as a special case of a blocking queue: The semaphore's "count" is the number of items that are in the queue, but the items themselves contain no information. Just as any thread is allowed put an item into a blocking queue, and any thread is allowed to take an item out, so any thread can increment or decrement the count of a semaphore.

Upvotes: 2

Related Questions