Снова про double-check locking
От: Аноним  
Дата: 10.11.13 20:02
Оценка:
Есть такой код


        private const string ContainerKey = "ModelsKey";
        private static object _sync=new object();
        private ConcurrentDictionary<string, Model> Container
        {
            get
            {
                var tmp = HttpContext.Current.Application[ContainerKey] as ConcurrentDictionary<string, Model>;
                if (tmp == null)
                {
                    lock (_sync)
                    {
                        tmp=HttpContext.Current.Application[ContainerKey] as ConcurrentDictionary<string, Model>;
                        if (tmp!=null)
                        {
                            return tmp;
                        }
                        tmp = new ConcurrentDictionary<string, Model>();
                        HttpContext.Current.Application[ContainerKey] = tmp;
                    }
                }
                return tmp;
            }
        }


1. Решарпер говорит, что внутри lock'а строка tmp=HttpContext.Current.Application[ContainerKey] — не нужна и tmp все равно равен null. Я ему не верю. Кто прав?
2. Является ли пример потокобезопасным?
Re: Снова про double-check locking
От: Sharov Россия  
Дата: 10.11.13 20:43
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>1. Решарпер говорит, что внутри lock'а строка tmp=HttpContext.Current.Application[ContainerKey] — не нужна и tmp все равно равен null. Я ему не верю. Кто прав?


Решарпер не прав.

А>2. Является ли пример потокобезопасным?

да
Кодом людям нужно помогать!
Re: Снова про double-check locking
От: mucks  
Дата: 11.11.13 05:14
Оценка:
Здравствуйте, Аноним, Вы писали:

А>2. Является ли пример потокобезопасным?


Не является. HttpContext.Current.Application глобальная переменная, а объект синхронизации в пределах класса.
Re: Снова про double-check locking
От: drol  
Дата: 11.11.13 05:27
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>2. Является ли пример потокобезопасным?


Формально — нет. Бо свойство Application не является потокобезопасным.
Re[2]: Снова про double-check locking
От: Аноним  
Дата: 11.11.13 07:56
Оценка:
Здравствуйте, mucks, Вы писали:

M>Здравствуйте, Аноним, Вы писали:


А>>2. Является ли пример потокобезопасным?


M>Не является. HttpContext.Current.Application глобальная переменная, а объект синхронизации в пределах класса.


Я правильно Вас понимаю, Вы предлагаете использовать что-то вроде lock(HttpContext.Current.Application) ?

Хочется понять есть ли в этом смысл.
У меня ситуация следующая: в Application (а так же в Session) хранится куча строго-типизированных коллекций. По аналогии с приведенным примером, но ContainerKey отличается.
Гарантируется, что доступ к данным коллекциям происходит только через свойство Container (private), и никто напрямую с Application/Session работать не будет. Не вижу необходимости синхронизировать любое добавление в Application/Session, что плохого случится если одновременно будет добавляться элементы с ключами "ModelsKey" и "OtherModelsKey" ?
Re: Снова про double-check locking
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 11.11.13 07:58
Оценка: 6 (1)
Здравствуйте, Аноним, Вы писали:

А>Есть такой код



А>
А>        private const string ContainerKey = "ModelsKey";
А>        private static object _sync=new object();
А>        private ConcurrentDictionary<string, Model> Container
А>        {
А>            get
А>            {
А>                var tmp = HttpContext.Current.Application[ContainerKey] as ConcurrentDictionary<string, Model>;
А>                if (tmp == null)
А>                {
А>                    lock (_sync)
А>                    {
А>                        tmp=HttpContext.Current.Application[ContainerKey] as ConcurrentDictionary<string, Model>;
А>                        if (tmp!=null)
А>                        {
А>                            return tmp;
А>                        }
А>                        tmp = new ConcurrentDictionary<string, Model>();
А>                        HttpContext.Current.Application[ContainerKey] = tmp;
А>                    }
А>                }
А>                return tmp;
А>            }
А>        }
А>


А>1. Решарпер говорит, что внутри lock'а строка tmp=HttpContext.Current.Application[ContainerKey] — не нужна и tmp все равно равен null. Я ему не верю. Кто прав?

Он неправ

А>2. Является ли пример потокобезопасным?

It depends. Если никто другим способом не лезет доставать твой контейнер, то да.
А вообще double-check lock может отказаться непотокобезопасным, это надо помнить.

Кстати лучше пользоватся http://msdn.microsoft.com/en-us/library/system.web.httpapplicationstate.lock(v=vs.110).aspx, а не ручной блокировкой.
Re[2]: Снова про double-check locking
От: Аноним  
Дата: 11.11.13 08:15
Оценка:
Здравствуйте, gandjustas, Вы писали:

А>>2. Является ли пример потокобезопасным?

G>It depends. Если никто другим способом не лезет доставать твой контейнер, то да.
G>А вообще double-check lock может отказаться непотокобезопасным, это надо помнить.

Можно пример, когда это будет непотокобезопасным? Если вы имеете ввиду вариант, когда вместо локальный переменной использования не-volatile поля класса, то про это я знаю, но у меня вроде как lock должен гарантировать отсутствие сайд-эффектов от переупорядочиваний/кеширований и прочей_магии.

G>Кстати лучше пользоватся http://msdn.microsoft.com/en-us/library/system.web.httpapplicationstate.lock(v=vs.110).aspx, а не ручной блокировкой.

Про это я написал в ответ на сообщение mucks. У меня гарантируется доступ к элементу коллекции Application через свойство Container, и я не вижу смысл синхронизировать любые попытки добавления в коллекцию.
Хотя особых минусов блокировать все коллекцию я не вижу — наверное кину монетку =)
Re[3]: Снова про double-check locking
От: mucks  
Дата: 11.11.13 17:53
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Я правильно Вас понимаю, Вы предлагаете использовать что-то вроде lock(HttpContext.Current.Application) ?


Нет, я этого не предлагаю В общем случае, возможность несинхронизированного доступа остается такая же.

А>Хочется понять есть ли в этом смысл.

А>У меня ситуация следующая: в Application (а так же в Session) хранится куча строго-типизированных коллекций. По аналогии с приведенным примером, но ContainerKey отличается.
А>Гарантируется, что доступ к данным коллекциям происходит только через свойство Container (private), и никто напрямую с Application/Session работать не будет. Не вижу необходимости синхронизировать любое добавление в Application/Session, что плохого случится если одновременно будет добавляться элементы с ключами "ModelsKey" и "OtherModelsKey" ?

Если это только ваш код и вы уверены, что описанные допущения нарушены не будут, то проблем с многопоточностью не будет. И даже Container можно паблик сделать. Но строго говоря код не является потокобезопасным, поскольку защищаемые данные видны всем.
Re: Снова про double-check locking
От: IvaDuke Россия  
Дата: 13.11.13 09:29
Оценка:
В ReSharper 8.1 уже исправлено и работает как надо
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.