Есть ли проблема с безопасностью потоков в этом коде ObjectBuilder?

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

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

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

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

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;
}

1 ответ

Решение
  1. Использование хеш-кода выглядит проблематичным, если вы запускаете очень большое количество классов / членов, что может случиться с упомянутым вами одноэлементным подходом.
  2. The double lock was totally odd in the old one (Only one thread goes into the whole section in all cases). Note that locking as the first thing certainly hurts performance. It is a trade of, notice that instead they create a copy to avoid modifying the list as it is being read.
Другие вопросы по тегам