Приветствую! Вопросов два.
Первый. Как же все-таки правильно, "
кеш" или "
кэш"? Помнится в ВУЗе учили, что кеш. Очень хорошо запомнил. А потом гляжу, так продвинутые пишут "кэш". Гуглохром упорно делает вид, что вообще не знает оба слова. Это, так сказать, лирическое вступление, чтобы создать настроение
Второй (и самый важный!). Снова думаю о чудесном расчудесном 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 окажется в словаре только после прохождения барьера, который должен обеспечить полную инициализацию объекта.
А может я вообще здесь все нагнал. Просвятите, плиз!