Страницы

Поиск по вопросам

вторник, 17 декабря 2019 г.

Нахождение многопоточных проблем

#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. Такое очень чревато и нафиг никому не нужно, как вы понимаете.

Комментариев нет:

Отправить комментарий