2016-07-27 2 views
-2

У меня есть следующий код с единственным производителем и одной потребительской нитью, но некоторые из них как-то заходят в мертвую блокировку. Я пытаюсь достичь аналогичной функциональности, если java условная переменная с C#, но я искал ее, но не нашел ничего близкого к ней. Любая помощь в этом отношении будет высоко оценена.Dead Lock in Producer Consumer C# Ограниченная очередь

`

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); 
       } 
      } 

     } 

    } 
} 

}

`

+0

Если это не учебное упражнение, не беспокойтесь писать свою собственную очередь. Для однопоточного использования используйте [Очередь ] (https://msdn.microsoft.com/en-us/library/7977ey2c (v = vs.110) .aspx). Для многопоточных программ используйте [BlockingCollection] (https://msdn.microsoft.com/en-us/library/dd267312 (v = vs.110) .aspx). –

+0

См. Http://stackoverflow.com/questions/15657637/condition-variables-c-net для примера использования переменных условия в C#. Кроме того, Стивен Туб сделал блокирующую очередь в C# 10 лет назад: https://blogs.msdn.microsoft.com/toub/2006/04/12/blocking-queues/ –

+0

да, это учебное упражнение, которым вы поделились, полезно в этом отношении – pannu

ответ

0

я пропустил трюк, когда-либо производитель или потребитель получить уведомление после Monitor.wait (это), они должны повторять попытки добавления элемента в список вниз - правильный код для производителя и потребителя. Я тестировал эти две функции с 100 потоками производителей и 10 потоками потребителей. с размером очереди 10 100,1000, и это работало нормально

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); 
      } 

     } 

    }