«без блокировки» не означает, что потоки не будут блокировать друг друга. Это означает, что они блокируют друг друга с помощью очень эффективных, но и очень хитрых механизмов. Требуется только для сценариев с очень высокой производительностью, и даже эксперты ошибаются (много).
Лучший совет: забудьте «без блокировки» и просто используйте «потокобезопасную» очередь.
Я бы порекомендовал "Очередь блокировки" с этой страницы .
И это вопрос выбора - включить ThreadRoutine
(Потребителя) в сам класс.
Что касается второй части вашего вопроса, это зависит от того, что именно представляет собой «какое-то событие синхронизации». Если вы собираетесь использовать вызов метода, тогда позвольте этому запустить одноразовый поток. Если вы хотите подождать на семафоре, чем , не используйте Monitor and Pulse. Они не надежны здесь. Использовать AutoResetEvent / ManualResetEvent.
Как это зависит от того, как вы хотите его использовать.
Ваши основные ингредиенты должны выглядеть следующим образом:
class Logger
{
private AutoResetEvent _waitEvent = new AutoResetEvent(false);
private object _locker = new object();
private bool _isRunning = true;
public void Log(string msg)
{
lock(_locker) { _queue.Enqueue(msg); }
}
public void FlushQueue()
{
_waitEvent.Set();
}
private void WorkerProc(object state)
{
while (_isRunning)
{
_waitEvent.WaitOne();
// process queue,
// ***
while(true)
{
string s = null;
lock(_locker)
{
if (_queue.IsEmpty)
break;
s = _queue.Dequeu();
}
if (s != null)
// process s
}
}
}
}
Часть обсуждения, по-видимому, связана с тем, что делать при обработке очереди (помеченной ***
). Вы можете заблокировать очередь и обработать все элементы, во время которых добавление новых записей будет заблокировано (дольше), или заблокировать и получать записи по одной и только блокировать (очень) каждый раз каждый раз. Я добавил этот последний сценарий.
Резюме. Вам нужно не решение без блокировки, а без блокировки. Block-Free не существует, вам придется согласиться на то, что блокирует как можно меньше. Последняя итерация mys sample (неполная) показывает, как блокировать только вызовы Enqueue и Dequeue. Я думаю, что это будет достаточно быстро.