-2

I have the following code with single producer and a single consumer thread but the they some how get into dead lock. I am trying to achieve similar functionality if java conditional variable with C# but I have searched around but didn't find any thing close to it. Any help in this regard would be highly appreciated.

`

    private List<T> coffeeBevrages;
    private volatile int count;
    private int max;
    private int consumed = 0;
    static Semaphore pool;

    public Queue() 
    {
        max = 10;
        pool = new Semaphore(0, max);
        count = 0;
        coffeeBevrages = new List<T>();
    }
    public void busyAdd(T name)
    {
        while (!add(name)) Console.WriteLine("producesr busy");
    }
    public void busyRemove(T name)
    {
        while (!remove(name)) Console.WriteLine("consumer busy"); 
    }
    private bool add(T name)
    {
        lock(this)
        {
            if (count < max)
            {
                count++;
                coffeeBevrages.Add(name);
                return true;
            }
            else
                return false;

        }   

    }
    private bool remove(T name) 
    {
        lock (this) 
        {
            if (count > 0)
            {

                count--;
                Console.WriteLine(coffeeBevrages.Remove(name));
                consumed++;
                Console.WriteLine(consumed);
                return true;
            }
            else
                return false;

        }

    }
    public void sleepAdd(T name)
    {
        Console.WriteLine("Hey......################");
        #region locking code
        lock (this)
        {
            if (count < max)
            {
                count++;
                consumed++;
                Console.WriteLine("Produced : " + consumed);
                Console.WriteLine("Here notification p " + count);                                                                                                                                                             
                coffeeBevrages.Add(name);
                Monitor.PulseAll(this);
            }
            else 
            {
                while (count == max) 
                {
                    Console.WriteLine("Here " + count);
                    Monitor.Wait(this,100);
                }
            }
        #endregion
        }   

    }
    public void sleepremove(T name) 
    {
        lock (this)
        {
            if (count > 0)
            {

                Console.WriteLine("Here notification c " + count);
                count--;
                Monitor.PulseAll(this);
            }
            else
            {
                while (count == 0) 
                {
                    Console.WriteLine("Here" + count);
                    Monitor.Wait(this,100);
                }
            }

        }

    }
}

}

`

pannu
  • 518
  • 7
  • 20
  • Unless this is just a learning exercise, don't bother writing your own queue. For single-threaded use, use [Queue](https://msdn.microsoft.com/en-us/library/7977ey2c(v=vs.110).aspx). For multi-threaded programs, use [BlockingCollection](https://msdn.microsoft.com/en-us/library/dd267312(v=vs.110).aspx). – Jim Mischel Jul 27 '16 at 16:04
  • See http://stackoverflow.com/questions/15657637/condition-variables-c-net for an example of using condition variables in C#. Also, Stephen Toub did a blocking queue in C# 10 years ago: https://blogs.msdn.microsoft.com/toub/2006/04/12/blocking-queues/ – Jim Mischel Jul 27 '16 at 16:05
  • yes its a learning exercise the content you shared is helpful in this regard – pannu Jul 27 '16 at 16:22
  • Deadlock requires two or more locks. You have two (`lock(this)` and `pool`), but the code above doesn't use `pool`, so doesn't show how deadlock could occur. Please provide a good [mcve] that reliably reproduces the problem. Please explain more precisely the circumstance in which you observe deadlock, and explain why you believe it's deadlock as opposed to some other blocking issue. – Peter Duniho Jul 27 '16 at 17:39
  • Yes it was not deadlock problem, I identified it at latter stage and remedied it. I will be posting the answer to this. It was the problem of starvation because the producer or consumer when called Monitor.wait(this), after getting the notification checked the condition in while and if the condition has been satisfied didn't produced or consumed any thing. That was the reason I was getting a starvation problem when both of them(producer and consumer) waited on Monitor.wait(this). I will be posting the remedied solution that worked for me. – pannu Jul 28 '16 at 08:27

1 Answers1

0

I missed the trick when ever a producer or consumer get notified after Monitor.wait(this) they need to retry adding the element into the list down is correct code for producer and consumer I tested these two functions with 100 producer threads and 10 consumer threads. with queue size 10,100,1000 and this worked fine

public void sleepAdd(T name)
    {
        #region locking code
        lock (this)
        {
            if (count < max)
            {
                count++;

                coffeeBevrages.Add(name);
                Monitor.PulseAll(this);
            }
            else 
            {
                while (count == max) 
                {
                    Console.WriteLine("Producer to Sleep");
                    Monitor.Wait(this);
                }
                sleepAdd(name);
            }
        #endregion
        }   

    }
    public void sleepremove(T name) 
    {
        lock (this)
        {
            if (count > 0)
            {
                consumed++;
                Console.WriteLine(consumed);
                count--;
                Monitor.PulseAll(this);
            }
            else
            {
                while (count == 0) 
                {
                    Console.WriteLine("Consumer to Sleep");
                    Monitor.Wait(this);
                }
                sleepremove(name);
            }

        }

    }
pannu
  • 518
  • 7
  • 20