Задний план
Я реализовал фрагмент кода на C#, который эквивалентен производителю со многими потребителями, использующими методы ожидания и PulseAll монитора.
Я хотел бы предоставить производителю возможность подождать, прежде чем производить, пока все потребители не будут ждать.
Это упрощенная реализация потребительской стороны:
lock (_lock)
{
while (! _condition)
{
Monitor.Wait(_lock);
}
}
А это упрощенная реализация на стороне производителя:
lock (_lock)
{
_condition = true;
Monitor.PulseAll(_lock);
}
Это хорошо известный шаблон, который довольно эффективен и хорошо работает в моем случае.
Проблема
В некоторых случаях я хотел бы, чтобы производитель ждал, прежде чем вызывать приведенный выше код производителя, пока все потребители не окажутся внутри вызова Monitor.Wait()
.
Концепция решения для единого потребителя
Упростим вопрос для случая одного потребителя. Решение требует, чтобы производитель ждал дополнительный объект синхронизации, о котором потребитель может сигнализировать атомарно при его входе в Monitor.Wait()
.
Концепция решения для нескольких потребителей
Обобщая вышеприведенное решение, все потребители должны получить доступ к потокобезопасному счетчику, который инициализируется количеством потребителей.
Каждый потребитель автоматически вызовет Monitor.Wait()
и уменьшит значение счетчика. Также в атомарном вызове каждый потребитель будет проверять, равен ли счетчик нулю после уменьшения, и если это так, повторно инициализирует счетчик и сигнализирует производителю.
Резюме
в реализации производителя и нескольких потребителей на С# мне нужно разрешить производителю ждать, пока все потребители перейдут в состояние ожидания, прежде чем производить.
Я не нашел способ реализовать это на основе мониторов.
Я бы предпочел решение, основанное на мониторах, но если бы совершенно другой подход сделал это проще, это тоже было бы здорово.