Обработка проблем параллелизма в многопоточном сервисе - PullRequest
0 голосов
/ 07 февраля 2019

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

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple)]   
public class CalculatorService : ICalculatorConcurrency   
{   
    ...  
}  

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

Правильно ли я обработал параллелизм, как показано ниже?Могут быть различные случаи, когда клиент обращается к сервису, например:

  • Клиент1, использующий службу словаря для изменения ()
  • Клиент2, использующий словарь службы для очистки ()
  • Клиент3, использующий сервис для чтения () словаря

Пример кода выглядит следующим образом:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple)]
    public class CalculatorService : ICalculatorConcurrency
    {   
        private static int clientId;
        private static object lockObject = new object();
        private static Dictionary<int, Number> numberList = new Dictionary<int, Number>();


    public static Number ReadNumber(int n)
    {
        Number info;
        lock (lockObject)
        {
            if (!numberList.TryGetValue(n, out info))
            ...
        }
    }

    public static bool Modify(Number number)
    {
        lock (lockObject)
        {
            ...
        }
    }

    public bool Clear()
    {
        lock (lockObject)
        {
            numberList.Clear();
            ...
        }               
    }
}

Безопасен ли мой поток кода?Или, более того, правильно ли я это делаю?

1 Ответ

0 голосов
/ 08 февраля 2019

Поскольку вы используете только один ресурс (т. Е. lockObject), взаимоблокировки невозможны.Чтобы зайти в тупик, нужно иметь как минимум два ресурса.

Безопасен ли поток моего кода?

Если вы используете Dictionary<,>, чтобы избежать проблем с параллелизмом, каждое взаимодействие с этим словарем должно быть заключено в lock(lockObject){}, поскольку высделал.Итак, ваш код является поточно-ориентированным.

Я делаю это правильно?

Вы делаете правильно, но если вы используете .Net 4 или новее, вам удобнеевариант с резьбовым безопасным ConcurrentDictionary<TKey,TValue>.Он был разработан специально для таких случаев, как ваш.Разница в том, что вы можете забыть о lock блоках.Он не будет генерировать исключение, когда один вызывающий абонент просматривает словарь, а второй вызывающий изменяет словарь.ConcurrentDictionary<TKey,TValue> реализует IDictionary<TKey,TValue> и, кроме того, предоставляет удобные методы, такие как TryAdd, TryUpdate и др.

Итак, вам определенно нужно использовать ConcurrentDictionary, если это возможно, так какделает код чище.

...