И снова про MemoryBarrier... Кэшируем объекты в Dictionary
От: MxMsk Португалия  
Дата: 12.01.11 14:26
Оценка:
Приветствую! Вопросов два.

Первый. Как же все-таки правильно, "кеш" или "кэш"? Помнится в ВУЗе учили, что кеш. Очень хорошо запомнил. А потом гляжу, так продвинутые пишут "кэш". Гуглохром упорно делает вид, что вообще не знает оба слова. Это, так сказать, лирическое вступление, чтобы создать настроение

Второй (и самый важный!). Снова думаю о чудесном расчудесном MemoryBarrier. Перечитал веточки здесь, маны поглядел — уже думаю за бутылку браться, так меня многопоточное разводилово клинит, что хочется напиться и забыться. Но нет! Путь из формошлепщика в гуру тяжел — будем бороцца!

Итак, есть такой код:
public static class PropertyChangedHelper
{
    private static readonly Dictionary<string, PropertyChangedEventArgs> _EventArgsCache = new Dictionary<string, PropertyChangedEventArgs>();

    public static PropertyChangedEventArgs GetEventArgs(string propertyName)
    {
        PropertyChangedEventArgs eventArgs;
        bool found = PropertyChangedHelper._EventArgsCache.TryGetValue(propertyName, out eventArgs);

        if (!found)
        {
            lock (PropertyChangedHelper._EventArgsCache)
            {
                if (!PropertyChangedHelper._EventArgsCache.TryGetValue(propertyName, out eventArgs))
                {
                    eventArgs = new PropertyChangedEventArgs(propertyName);
                    PropertyChangedHelper._EventArgsCache.Add(propertyName, eventArgs);
                }
            }
        }

        return eventArgs;
    }
}


Так вот я задумался: есть ли здесь необходимость в барьерах? Может ли так случиться, что из-за переупорядочивания, объект eventArgs окажется в словаре до того, как его свойство PropertyName получит нужное значение? Это в свою очередь может привести к тому, что другой поток, увидит в словаре данные с тем же ключом, не увидит никакого барьера и вернет еще невалидный объект. В связи с этим подумалось, может нужно так?

public static class PropertyChangedHelper
{
    private static readonly Dictionary<string, PropertyChangedEventArgs> _EventArgsCache = new Dictionary<string, PropertyChangedEventArgs>();

    public static PropertyChangedEventArgs GetEventArgs(string propertyName)
    {
        PropertyChangedEventArgs eventArgs;
        bool found = PropertyChangedHelper._EventArgsCache.TryGetValue(propertyName, out eventArgs);

        if (found)
        {
            Thread.MemoryBarrier();
        }
        else        
        {
            lock (PropertyChangedHelper._EventArgsCache)
            {
                if (!PropertyChangedHelper._EventArgsCache.TryGetValue(propertyName, out eventArgs))
                {
                    eventArgs = new PropertyChangedEventArgs(propertyName);
                    Thread.MemoryBarrier();
                    PropertyChangedHelper._EventArgsCache.Add(propertyName, eventArgs);
                }
            }
        }

        return eventArgs;
    }
}



Но здесь мне кажется первый барьер точно не нужен. Да, я понимаю, что барьер — это игра двух. Это я запомнил Но ведь eventArgs окажется в словаре только после прохождения барьера, который должен обеспечить полную инициализацию объекта.

А может я вообще здесь все нагнал. Просвятите, плиз!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.