Обновить
58

Пользователь

51
Подписчики
Отправить сообщение
Я от этого далеко и не отхожу:

1. изучена работа typeof и Type
2. выдвинута чёткая гипотеза, что TypeOf и RipeType могут работать быстрее в некоторых сценариях
3. разработан и проведён ряд повторяемых экспериментов, в том числе опровергающих гипотезу

Получены результаты и предоставлены на рассмотрение широкому сообществу. :)
Я дискутирую, а не доказываю и, как видите, при наличии убедительных аргументов, готов признавать свои ошибки.

Во-первых, даже опытные разработчики могут не увидеть проблемы в своём коде, которая выльется в виде бага.

Во-вторых, некоторые подозрительные места я замечаю и мне наоборот весьма интересно провеить их в нестандартных условиях.

Для меня подобные публикации что-то вроде код-ревью от сообщества, с чем-то соглашаюсь, с чем-то нет.
Кстати, ваш словарь еще и публичный, поэтому все и любые утверждения про то, что модификация только под локом, невалидны.

Спасибо, в коде я это уже подправил, а в статье осталась неточность, подкорректирую.

Вот только вы можете получить true и null.
Может быть, и могу. Но дело в том, что у меня такая позиция в программировании — испытывать на прочность самые неожиданные сценарии и варианты, а не ходить по проторенным и безопасным тропинкам. :)

Конечно, в коммерческих рабочих проектах я обычно применяю более надёжные решения, но в своих исследовательских ни в чём таком себя не сдерживаю.
Да, потенциально (хотя не стопроцентный факт, но для меня убедительный) это место может упасть с ArgumentOutOfRangeException из-за возможной гонки при присваивании в две переменные, как упомянул в комментариях retran.
Любопытно, с чем именно вы столкнулись при апгрейде? Мне просто интересно узнавать такие тонкости в реализациях стандартных классов.
Кстати, про syncroot на коллекциях вы не знаете, да?

Знаю, но в некоторых случаях мне хотелось бы абстрагироваться от введения явной переменной, отчего и появился
public static class Lock
{
	public static TResult Invoke<TSyncContext, TResult>(Func<TResult> func)
	{
		lock (func) return func();
	}
}

К сожалению, как верно указали, в случае замыканий переменных он работать не будет.

Потенциально возвращенный null вы тоже обрабатываете? Что-то не видно.

Обрабатывается потенциально возвращённый false. :)
Теперь убедили, потенциально тут может возникнуть ArgumentOutOfRangeException.
Да, каждый конкретный случай лучше рассматривать отдельно и выявлять наболее оптимальное решение, также стоит производить замеры на различных CLR, поскольку результаты иногда сильно плавают.
Моя цель — поделиться идеями, подвергуть их критике и приблизиться истине. Вот с примененим лока на делегате уже нашли изъян, и я признаю, что оказался не прав. :)

Думаю, это заставляет работать умы людей и более глубоко разбираться в вопросах.
Да, признаю, в этом предположении я оказался не прав. Нужно задавать более надёжный контекст для lock'а. Пример подправлю.
Изначально я придерживаюсь такого определения:
Словарь, не являясь потокобезопасным классом, способен работать в условиях нескольких потоков, но может давать ненадёжные результаты.
Пример интересный, но я не вижу аналогии с текущим случаем. Словарь внутри себя не дожидается выполнения потоков и не делает предположений, о значениях переменных. Грубо говоря, это просто массив, который может увеличиваться, сохраняя индексы элементов, с ненадёжным параллельным чтением (один поток может упустить изменения, только что внесённые другим).
Можно два определения дать потокобезопасности:
1. Гаранития того, что коллекция вообще будет работать в условиях нескольких потоков
2. Гарантия того, что при записи/удалении/замене элемента одним потоком, второй изменения сразу же увидит

Сейчас я придерживаюсь второго, более сильного. Словарь, не являясь потокобезопасным классом, способен работать в условиях нескольких потоков, но может давать ненадёжные результаты.
Запись элементов идёт только под lock'ом. То есть я допускаю лишь ситуацию с ненадёжным параллельным чтением, которая обрабатывается под тем же lock'ом.
Не вижу причин для падения даже при параллельном Clear.
Возможно, для других сценариев это критично, что накладывает ограничения на применение, но для конкретного допустимо.
Пока убедительных аргументов, почему метод используется неправильно, я не услышал. Исключений нет, как выяснили, другой элемент тоже не придёт в результате. Если даже элемен вдруг потеряется, что крайне маловероятно, то в нашем случае ничего серьёзного не произойдёт, создадим новый вместо прежнего.
Её, как будто, гарантируют CLR и компилятор при инициализации статической переменной
    [CompilerGenerated]
    private sealed class <>c
    {
        public static readonly <>c <>9 = new <>c();

(декомпиляция)

Сама идеология работы метода при правильной имплементации должна гарантировать отсутствие всяких исключений. Если исключения есть, значит, плохо реализован метод, в нём баг.
Нет, я не проверял все возможные сценарии и отталкиваюсь лишь от того, что TryGetValue возвращает true и сам элемент, если он присутствует в словаре по ключу, либо false если его там нет или он только что асинхронно добавлен в процессе чтения другим потоком (и на этот случай выполняется повторное чтение в критической секции).

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность