Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the proper way to wait on a Semaphore?

I thought that the following code would let all the 10 threads run, two at a time, and then print "done" after Release() is called 10 times. But that's not what happened:

        int count = 0;

        Semaphore s = new Semaphore(2, 2);
        for (int x = 0; x < 10; x++)
        {
            Thread t = new Thread(new ThreadStart(delegate()
            {
                s.WaitOne();
                Thread.Sleep(1000);
                Interlocked.Increment(ref count);                       
                s.Release();
            }));
            t.Start(x);
        }

        WaitHandle.WaitAll(new WaitHandle[] { s });
        Console.WriteLine("done: {0}", count);

output:

done: 6

If the only way to implement the functionality I'm looking for is to pass an EventWaitHandle to each thread and then do a WaitAll() on an array of those EventWaitHandles, then what's the meaning of doing a WaitAll() on an array of only a semaphore? In other words, when does the waiting thread unblock?

like image 799
John Smith Avatar asked Jan 25 '13 20:01

John Smith


People also ask

How do you wait on a semaphore?

The post (sem_post()) operation increments the semaphore; the wait (sem_wait()) operation decrements it. If you wait on a semaphore that is positive, you will not block. Waiting on a nonpositive semaphore will block until some other thread executes a post. It is valid to post one or more times before a wait.

What is application of wait () in semaphore?

The wait command P(S) decrements the semaphore value by 1. If the resulting value becomes negative then P command is delayed until the condition is satisfied. The V(S) i.e. signals operation increments the semaphore value by 1.

Is wait () semaphore accessed?

" Semaphore S is an integer variable that is accessed through standard atomic operations i.e. wait() and signal().

What is semaphore explain working of wait () and signal () operations?

A semaphore is a signaling mechanism, and a thread that is waiting on a semaphore can be signaled by another thread. It uses two atomic operations, 1) Wait, and 2) Signal for the process synchronization. A semaphore either allows or disallows access to the resource, which depends on how it is set up.


2 Answers

WaitHandle.WaitAll just waits until all the handlers are in signalled state.

So when you call WaitHandle.WaitAll on one WaitHandle it works the same as you call s.WaitOne()

You can use, for example, the following code to wait for all the started threads, but allow two threads to run in parallel:

int count = 0;

Semaphore s = new Semaphore(2, 2);
AutoResetEvent[] waitHandles = new AutoResetEvent[10];
for (int x = 0; x < 10; x++)
    waitHandles[x] = new AutoResetEvent(false);

for (int x = 0; x < 10; x++)
{
    Thread t = new Thread(threadNumber =>
        {
            s.WaitOne();
            Thread.Sleep(1000);
            Interlocked.Increment(ref count);
            waitHandles[(int)threadNumber].Set();
            s.Release();
        });
    t.Start(x);
}

WaitHandle.WaitAll(waitHandles);
Console.WriteLine("done: {0}", count);
like image 90
Nikolay Khil Avatar answered Sep 29 '22 03:09

Nikolay Khil


WaitHandle.WaitAll(new WaitHandle[] { s }); waits just like s.WaitOne();. It enters at the first opportunity. You seem to expect this call to wait for all other semaphore operations but there is no way the operating system can tell the difference. This command might well be the first that is granted access to the semaphore.

I think what you need is the Barrier class. It is made for fork-join-style parallelism.

like image 36
usr Avatar answered Sep 29 '22 02:09

usr