Как правильно использовать readerwriterlock

2

Здравствуйте, мне нужно использовать writereaderlock в моем методе. Я хочу знать, как правильно это использовать.

У меня есть словарь ObjectA

public class ObjectA
{
    public ReaderWriterLock RWL {get;set;}
    public ObjectB obj {get;set;}
    public ObjectA()
    {
        RWL = new ReaderWriterLock();
    }
}

public class ObjectB
{
    int TTL {get;set;}
    string Value {get;set;}
}

В моем методе я использую словарь ObjectA, ключ - Guid, поэтому предположим, что когда я вызываю dict [guid], он всегда возвращает экземпляр объекта ObjectA (для примера)

public foo()
{
    ObjecA objA = dict[guid];
    objA.RWL.AcquireReaderLock(500);
    if(objA.obj.TTL<=0)
    {
        objA.obj.RWL.AcquireWriterLock(1000);
        objA.obj.Value = DateTime.Now().ToString();
        objA.obj.RWL.ReleaseWriterLock();
    }else{
         int ttl = objA.obj.TTL;
         Interlocked.Decrement(ref ttl);
    }    
    objA.RWL.ReleaseReaderLock();
}

Я действительно не уверен в том, что я использую читателя и писателя там, как мне нужно было использовать блокировку писателя с условной проверкой?

  • 0
    Одно это наверняка, вы не правильно уменьшаете TTL. Вы атомарно уменьшаете переменную стека, а не члена класса.
Теги:
multithreading

1 ответ

6
Лучший ответ

В этом коде есть много проблем, включая:

  • вы на самом деле никогда не уменьшаете TTL в своем экземпляре класса, как указывает Николай, вы уменьшаете локальную переменную! Interlocked.Decrement(ref objA.obj.TTL) как это сделать правильно.
  • вы не устанавливаете начальное значение TTL, поэтому оно всегда будет равным нулю (если не будет установлен какой-либо другой код, что, вероятно, не имеет отношения к классу, чувствительному к потокам, где обычно требуется весь связанный с потоком код в том же классе, чтобы не потерять контроль над тем, кто что делает).
  • вы должны использовать ReaderWriterLockSlim, который теперь предпочитается более старым ReaderWriterLock. См. Последнюю гиперссылку для почему.
  • При приобретении блокировки записи, если у вас уже есть блокировка чтения, вам необходимо обновить блокировку - обычно для этого класса блокировки используется отдельный метод. Аналогично, после обновления, для освобождения блокировки требуется один способ освобождения блокировки, а не один, чтобы освободить блокировку записи, а другой - освободить предыдущую блокировку чтения.
  • вам нужно иметь дело с случаем сбоя, когда вы не можете приобрести блокировки.
  • вы захотите обернуть код в с помощью или try/finally, чтобы гарантировать освобождение ресурсов, даже если возникает исключение.

Также возможно стоит подумать, действительно ли вам нужно использовать блокировки чтения/записи вместо того, чтобы использовать что-то более простое, чем оператор lock{}. Правильно блокировать блокировки чтения/записи и избегать взаимоблокировок сложно даже для разработчиков, которые хорошо знают эти API и концепции, и даже тогда они обычно резервируют их использование только для самых критически важных мест (1000 + в секунду). Другими словами, вам может быть лучше начать с более простого подхода с использованием lock{} и вернуться к использованию ReaderWriterLockSlim, если производительность неприемлема.

В качестве отправной точки я бы предложил добавить дополнительную информацию к вашему вопросу:

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

Я гарантирую, что если вы включите эту дополнительную информацию в свой вопрос, вы получите лучшие ответы, которые помогут вам справиться с любыми остальными проблемами с кодом.: -)

  • 0
    Спасибо за ваш ответ, но код, который я показываю, был только примером, я использовал свой код в HttpHandler, блокировка действительно замедляет работу моего веб-приложения. Я попробую с ReaderWriterLockSlim Спасибо. Я обнаружил, что могу перевести мой читательский замок в писательский, и эта информация поможет мне. Спасибо
  • 0
    Отличный ответ - очень полезно!
Сообщество Overcoder
Наверх
Меню