#c_sharp #net #многопоточность
У меня снова глупый вопрос про многопоточность. Как известно многопоточный код чреват многими ошибками которые не актуальны при однопоточном программировании. К тому же они весьма трудно уловимы. Часто бывает трудно искусственно смоделировать какой-либо баг который то появляется то исчезает при работе приложения потому что сложно предсказать как именно и когда именно два разных потока обратятся к данным так что это приведет к порче данных. К тому же у меня наверное еще не очень хорошо развито умение выискивать проблемные с точки зрения многопоточности места в коде. А теперь вопрос: есть ли какие-то рецепты как обнаруживать потенциальные проблемы многопоточного доступа к данным? Вот например блокировки lock. Есть ли какие-то верные признаки по которым можно было бы сказать что вот в этом коде использующем многопоточность нужен lock а вот тут не нужен? Особенно с учетом того что баги связанные с использованием потоков часто бывает трудно отловить? Как вообще локализуются такие проблемы при написании кода и как они отлавливаются при дебаге?
Ответы
Ответ 1
Первое правило многопоточности - не используйте многопоточность :) Блокировки и прочие види синхронизации нужны для разделения доступа к ресурсам из разных потоков. Использование одного и того же объекта (не класса, а именно объекта) всегда требует явной или неявной блокировки/синхронизации. Потенциально проблемные места: Явная статика Неявная статика (использование Singleton в коде, любые вызовы вида SomeClass.Instance) Явные (параметрами) или неявные (через замыкания) переданные в фоновые потоке объекты. Основные принципы починки проблемных мест: Переход на классы, явно поддерживающие многопоточность. Например, проблема из вашего соседнего вопроса решается заменой линейного поиска перебором Listна поиск по ключу в ConcurrentDictionary Ревью кода с точки зрения "предполагать что на каждом шаге другой поток обяхательно возьмет и все поменяет". Расстановка локов для предотвращения таких ситуаций. В случае проблем с многопоточностью при хранении данных - перекладываение проблем многопоточности из кода C# на сторонние системы (базу данных, очереди сообщений, nosql, кэш). Ответ 2
многопоточный код чреват многими ошибками которые не актуальны при однопоточном программировании. Никаких ошибок не будет, если писать правильно. Покамест в вашем коде нет объектов, которые могут меняться из разных потоков, то такое ни чем не чревато. Попробуйте ради интереса создать множество потоков, которые просто читают значение свойства в объекте следующего класса public class Mein { private int _Kalkulation; public Mein(int kalkulation) { _Kalkulation = kalkulation; } public int Kalkulation { get { return _Kalkulation; } } } Никогда не будет проблем с таким объектом, сколько бы потоков его не читали. Но, как только вы позволите менять значение свойства из разных потоков, то проблемы обязательно когда-нибудь дадут о себе знать, в виде неожиданных значений. Однозначно требуется синхронизация, если доступ происходит из разных потоков. Пример: счет в банке, который могут менять разные потоки. Например, по ордеру надо списать 100 единиц со счета. Поток проверяет количество единиц на счете, получает значение 120, и пока он выполняет какой-то расчет, другой поток снимает 100 со счета и первый поток также снимает 100. Такое очень чревато и нафиг никому не нужно, как вы понимаете.
Комментариев нет:
Отправить комментарий