2013-06-26 7 views
2

Я подозреваю, что проблема связана со старой версией ObjectBuilder, которая когда-то была частью проекта расширения WCSF и между тем перешла в Unity. Я не уверен, нахожусь ли я на правильном пути или нет, поэтому я надеюсь, что кто-то там обладает более компетентными навыками обеспечения безопасности потоков, чтобы объяснить, может ли это быть проблемой или нет.Есть ли проблема защиты потоков в этом коде ObjectBuilder?

Я использую эту (устаревшую) реализацию ObjectBuilder в веб-приложении ASP.Net WCSF и редко вижу в журналах, что ObjectBuilder жалуется, что какое-то конкретное свойство класса не может быть введено по какой-либо причине, проблема в том, что всегда, чтобы это свойство никогда не вводилось вообще. Собственность и класс постоянно меняются. Я проследил код до метода, в котором словарь используется для хранения информации о том, обрабатывается ли объект ObjectBuilder или нет.

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

Класс, который содержит этот код (ReflectionStrategy.cs), создается как Singleton, поэтому все запросы к моему веб-приложению используют этот класс для создания его объектов вида/страницы. Его словарь является частным поле, используется только в этом методе и заявил так:

private Dictionary<int, bool> _memberRequiresProcessingCache = new Dictionary<int, bool>(); 

private bool InnerMemberRequiresProcessing(IReflectionMemberInfo<TMemberInfo> member) 
{ 
    bool requires; 

    lock (_readLockerMrp) 
    { 
     if (!_memberRequiresProcessingCache.TryGetValue(member.MemberInfo.GetHashCode(), out requires)) 
     { 
      lock (_writeLockerMrp) 
      { 
       if (!_memberRequiresProcessingCache.TryGetValue(member.MemberInfo.GetHashCode(), out requires)) 
       { 
        requires = MemberRequiresProcessing(member); 
        _memberRequiresProcessingCache.Add(member.MemberInfo.GetHashCode(), requires); 
       } 
      } 
     } 
    } 
    return requires; 
} 

Этот код выше не последняя версия, которую вы можете найти на Codeplex, но я все еще хочу знать, может ли это быть причиной мои исключения ObjectBuilder. Пока мы говорим, я работаю над обновлением, чтобы заменить этот старый код на последнюю версию. Это последняя реализация, к сожалению, я не могу найти никакой информации, почему она была изменена. Может быть, ошибка, может быть для исполнения ...

private bool InnerMemberRequiresProcessing(IReflectionMemberInfo<TMemberInfo> member) 
{ 
    bool requires; 

    if (!_memberRequiresProcessingCache.TryGetValue(member.MemberInfo, out requires)) 
    { 
    lock (_writeLockerMrp) 
    { 
     if (!_memberRequiresProcessingCache.TryGetValue(member.MemberInfo, out requires)) 
     { 
     Dictionary<TMemberInfo, bool> tempMemberRequiresProcessingCache = 
      new Dictionary<TMemberInfo, bool>(_memberRequiresProcessingCache); 
     requires = MemberRequiresProcessing(member); 
     tempMemberRequiresProcessingCache.Add(member.MemberInfo, requires); 
     _memberRequiresProcessingCache = tempMemberRequiresProcessingCache; 
     } 
    } 
    } 
    return requires; 
} 
+0

Также полезно было бы предложить как настроить тест, который может ответить на вопрос, подвержен ли этот код многопоточным ошибкам. – Eulinky

ответ

1
  1. Использование хэша-коды выглядит проблематичным, если у вас слишком большое количество классов/членов, как это бывает с одноплодным подходом, упоминается.
  2. Двойной замок был совершенно странным в старой (только одна нить входит во всю секцию во всех случаях). Обратите внимание, что блокировка в качестве первой вещи, безусловно, ущемляет производительность. Это торговля, обратите внимание, что вместо этого они создают копию, чтобы избежать изменения списка, когда он читается.
+0

Я установил синтетический тест нагрузки, чтобы генерировать большое количество классов как многопользовательских, так и однопоточных, и оказалось, что это хэш-код, вызвавший коллизии даже в настройке одиночного потока. Таким образом, нет доказательств для многопоточной задачи. Благодарю eglasius! – Eulinky

+2

Я хочу добавить, что примерно с 200 различными классами и 16 000 членов я столкнулся с конфликтом после создания 9 миллионов объектов, что означает примерно через 30 минут в моем приложении. однако последняя реализация кода работает нормально. – Eulinky

+0

_Works fine_ не является approriate: новый код медленнее, особенно из-за создания временного словаря - чем больше потоков у вас есть, тем медленнее создается ObjectBuilder. Теперь мы используем новый код, но избегаем temp dict и пишем непосредственно ему. Обширные тесты показали, что до сих пор нет никаких проблем, даже если больше нет блокировки чтения, возможно, из-за того, что dict объявлен изменчивым. – Eulinky