2

I'm working on semaphore using C#. The following is my understanding about the Release and WaitOne methods in C#.

The WaitOne method decreases the semaphore count when a thread enters a slot and when it leaves the slot, the semaphore is incremented.

The Release method returns the previous semaphore count right? My understanding contradicts with the following code :

  static Thread[] threads = new Thread[5];
        static Semaphore sem = new Semaphore(3,5);
        static void SemaphoreTest()
        {
            Console.WriteLine("{0} is waiting in line...", Thread.CurrentThread.Name);
            Console.WriteLine("Semaphore count : "+sem.WaitOne());
            Console.WriteLine("{0} enters the semaphore test", Thread.CurrentThread.Name);
            Thread.Sleep(300);

            Console.WriteLine("{0} is leaving the semaphore test and the semaphore count is {1}", Thread.CurrentThread.Name, sem.Release());

        }
        static void Main(string[] args)![enter image description here][2]
        {
            for (int i = 0; i < 5; i++)
            {
                threads[i] = new Thread(SemaphoreTest);
                threads[i].Name = "thread_" + i;
                threads[i].Start();

            }
            Console.Read();

Thread_2 leaves and hence the semaphore count must be incremented. But that is not happening as the previous semaphore count is 0 when thread_0 is about to leave. As per my understanding it must be one. Am I right? Could anyone explain this?

Brendan Green
  • 11,676
  • 5
  • 44
  • 76
vishnu
  • 511
  • 1
  • 7
  • 10
  • 4
    0 is entirely normal, a likely accident is that threads 0, 1 and 2 entered the semaphore. Seeing 1 is normal as well. You are making a very dangerous assumption, there is no guarantee whatsoever that the threads will acquire the semaphore in order. – Hans Passant May 03 '15 at 22:48

1 Answers1

1

The documentation describes the return value of the Release() method like this:

The count on the semaphore before the Release method was called

Note that this is different from saying that the method returns the value the semaphore had just before being released.

In particular, if you have two threads racing to release the semaphore, they could both call Release() at effectively the same time, causing this value to be identical for both threads. That is, calling the method is not entirely the same as actually releasing the semaphore; the method has to do some work before the semaphore is actually released, and the semaphore's count remains whatever it was until that actually happens.

I will also point out: at least when I run the test, I see thread #3 acquiring the semaphore before thread #0 reports leaving. Now, we don't know for sure what order these operations actually happened (the console output may or may not actually be exactly the same order as the threads' interactions with the semaphore), but another possibility is that thread #3 acquired the semaphore after thread #2 released it, but before thread #0 released it.

There are a number of valid scenarios in which you would see a count of 0 returned consecutively.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136