Use of Waitall in C#

Asked

Viewed 135 times

7

I have the following problem:

A program generates two types of A and B threads through clicks on their respective buttons. The two types cannot run at the same time. If I have 10 A threads, B can only run when the 10 A threads are finished.

I can restrict the input, creating a mutex for each type and a boolean variable that tells me whether or not there are threads of the other type being executed. However, when the first thread is finished, the opposite one can enter the critical region because I am using the nameMutex.Waitone().

How can I adapt the use of 'Waitall' to this situation? I couldn’t quite understand the concept.

1 answer

6


It is possible to solve this problem using:

  • one Mutex (lock)
  • two meters, one for A and one for B
  • and two manual reset events ManualResetEventSlim

    The ManualResetEventSlim serves to stop execution when you reach the method Wait, but only if in a state não-setado (there are two states, setado and não-setado). Threads can call the method Set to put the object in a state setado, or Reset to put in state não-setado.

  • example: an easy implementation, would be as below. This code however does not take care of cases and starvation, which is when As or Bs can be stopped from running, if the opposite type thread enters more frequently than the processor is able to run them... so the number of threads of the opposite type only increases.

    private static int a = 0;
    private static int b = 0;
    private static readonly object locker = new object();
    private static readonly ManualResetEventSlim mreA = new ManualResetEventSlim(true);
    private static readonly ManualResetEventSlim mreB = new ManualResetEventSlim(true);
    
    static void A()
    {
        while (true)
        {
            lock (locker)
            {
                // se não tem Bs executando, então o A pode executar
                if (b == 0)
                {
                    // o A vai executar, então devemos:
                    //  - impedir o acesso de Bs
                    //  - incrementar o contador de As
                    mreB.Reset();
                    a++;
                    break;
                }
            }
    
            // já tem Bs executando, vamos ficar esperando um sinal para continuar A
            mreA.Wait();
        }
    
        Console.WriteLine("A está executando");
    
        lock (locker)
        {
            // o A terminou, então:
            //  - decrementamos o contador de As
            //  - liberamos os Bs, se não houver mais As executando
            a--;
            if (a == 0)
                mreB.Set();
        }
    }
    
    static void B()
    {
        while (true)
        {
            lock (locker)
            {
                // se não tem As executando, então o B pode executar
                if (a == 0)
                {
                    // o B vai executar, então devemos:
                    //  - impedir o acesso de As
                    //  - incrementar o contador de Bs
                    mreA.Reset();
                    b++;
                    break;
                }
            }
    
            // já tem As executando, vamos ficar esperando um sinal para continuar B
            mreB.Wait();
        }
    
        Console.WriteLine("B está executando");
    
        lock (locker)
        {
            // o B terminou, então:
            //  - decrementamos o contador de Bs
            //  - liberamos os As, se não houver mais Bs executando
            b--;
            if (b == 0)
                mreA.Set();
        }
    }
    

Previous answer

Readerwriterlockslim

What are A and B? It seems to me the case of a Reader-Writer lock, where the reading can be performed several times at the same time, and the writing can be executed only if nothing else is running, neither other writing nor reading is being done.

If this is the case, it’s best to use a ReaderWriterLockSlim, which is part of the. Net framework, which serves precisely for this.

  • In fact, my problem looks more like that of the "Bathroom Unisex". I could say that A and B are men and women trying to use the same "bathroom". If you have A, only A can enter and B waits to empty. If you have B, only B can enter and A waits to empty.

  • I understand... in this case the ReaderWriterLockSlim does not really serve. I made an implementation using a Mutex, two ManualResetEventSlim and two accountants. It is not perfect (suffers from starvation), but it is a good start. See if it suits you, and tell me if you have doubt.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.