Синхронизация объектов с использованием ThreadPool

У меня есть несколько объектов процессора, которые я использую с ThreadPool, чтобы использовать их в параллельном процессе. Какой процессор я собираюсь использовать, в основном зависит от входящих данных, и может быть более 2000 различных типов; поэтому как только мое приложение запускается, оно создает 1-2K процессоров в словаре и запускает тот, который мне нужен, в соответствии с входящими данными в ThreadPool. Кстати, любой процесс не занимает больше миллисекунды.

Мой псевдо-код для работы в ThreadPool ниже:

public void onIncomingNewData(rawData)
{
     if (!ThreadPool.QueueUserWorkItem(processors[rawData.Type.Id].Process, rawData))
     {
         Console.WriteLine("Work item cannot be queued!");
      }

      //Thread.Sleep(1);
}

Моя проблема здесь в синхронизации объектов Processer; у них есть свой внутренний кеш, и я не хочу, чтобы несколько потоков выполняли один и тот же метод обработки объектов Process.

На данный момент я использую «блокировку» внутри метода процесса и некоторых других частных методов, которые обрабатывают вызовы методов. Но как лучше всего это сделать?


person Otake    schedule 05.02.2010    source источник
comment
Зависит от того, что вы имеете в виду под синхронизацией. Какова цель этой синхронизации?   -  person    schedule 05.02.2010


Ответы (2)


Что вам в основном нужно, так это пул процессоров, основанный на типе. Вместо кэширования фактического процессора в словаре процессоров создайте класс пула, который отслеживает доступные и активные процессоры. Когда поступит запрос, найдите подходящий пул. Затем посмотрите, есть ли доступные процессоры. Если это так, выньте его из доступного списка и поместите в активный список. Запустите метод Process, затем удалите его из активного списка и поместите в доступный список.

Вы можете обойтись без использования списков активных / доступных и вместо этого просто используйте активный флаг. В зависимости от количества одновременных процессов это может быть более эффективным.

Однако, если каждый вызов процесса занимает всего миллисекунду, это звучит как излишний для ваших конкретных нужд. Я бы порекомендовал использовать lock () для синхронизации и добавить запись в журнал, чтобы увидеть, как часто процессы ожидают блокировки. Если во время тестирования вы обнаружите, что это проблема, перейдите к чему-то более сложному.

Вам также, вероятно, потребуется заблокировать доступ к processors словарю, если он еще не является потокобезопасным. Если словарь предварительно загружен на 100%, в этом может быть нет необходимости.

person Samuel Neff    schedule 05.02.2010
comment
Согласен - это очень похоже на проблему, о которой Рид Копси недавно писал в блоге (на reedcopsey.com/2009/11/12/). Его ответ заключался в использовании локального хранилища потоков на уровне экземпляра, доступного в .NET 4.0. Если вы еще не используете 4.0, вероятно, лучшим решением будет пул. Как обнаружил Рид, блокировка общих данных процесса может свести на нет выигрыш в производительности, который вы получаете от распараллеливания, особенно для таких быстрых операций. - person Jeff Sternal; 05.02.2010

Вместо того, чтобы внедрять метод процессора в пул потоков, вместо этого пусть каждый процессор поддерживает свою собственную очередь запросов и внедряет свой собственный рабочий метод в пул потоков.

person Ed Power    schedule 05.02.2010