Вопрос. Порой в проектах нужно использовать дополнительные потоки для обработки информации. Но работать с потоками не просто, и встречаются различные проблемы. К примеру, рассинхронизация. Как научиться видеть и находить проблемы в многопоточном коде ПО используемых C#?

Ответ. Первое что нужно сделать — это разобраться в том инструменте, который вы используете для работы с многопоточным кодом. В данном случае это язык программирования C# и платформа .NET Framework или .NET Core.

Так как многие проблемы могут появляться именно от неправильного использования возможностей языка и платформы. И порой используют многопоточность там, где можно обойтись без нее.

Второе на мой взгляд — будет неплохо, если у вас будет понимание, как это все организуется на уровне памяти при обращении и получение данных.

Основные проблемы

В своей практике я встречался с двумя проблемами — это взаимоблокировки и когда два потока начинают делить ресурсы в итоге получается та сама рассинхронизация данных.

Для решения ситуации с рассинхронизацией, программисты в C# могут использовать оператор lock. Создавая объект заглушку. С его помощью можно синхронизировать выполнение потоков, когда они работают над общими ресурсами. Так же здесь хочу отметить, что существуют еще семафоры и мьютексы для работы с синхронизацией потоков.

Сам оператор lock определяет блок кода, внутри которого весь код блокируется и становится недоступным для других потоков до завершения работы текущего. После завершения работы текущего потока, к работе может приступить следующий поток, для выполнения нужных действий.

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

Это означает, что как минимум два потока ожидают освобождение ресурса для работы с ним. А ресурсы на текущий момент уже захвачены. Но так как эти два потока ожидают действие по освобождению ресурса друг от друга, то и получается взаимоблокировка. Из-за таких действий это ожидание может длиться бесконечно и приводит к тупиковой ситуации.

Поэтому если вы решили использовать многопоточное программирование, то определите строгую последовательность выполнение потоков, их блокировку и в каком порядке освобождать ресурсы. Задокументируйте все это. Чтобы было понятно, что и перед чем должно вызываться и почему. Чтобы другие разработчики тоже могли соблюдать этот подход.

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

Что в итоге

Работа с многопоточным кодом — тема, которой нужно уделить особое внимание разработчикам. Вне зависимости от того языка программирования и платформ, которые используют в работе.

Как ни крути знать теорию — хорошо, а понимать как это все можно сделать на практике — еще лучше. Чем больше ситуаций вы повстречаете с многопоточным кодом и решите, тем больше у вас будет понимание в чем может быть причина. И как ее лучше и быстрее решить.

Антон Чураков
Автор публикации
Антон Чураков

Работал .NET разработчиком в компании, занимающейся разработкой и внедрением системы BPM для автоматизации бизнес-процессов. На текущий момент - руководитель IT-компании «Цифровой Волк». Основное направление которой - заказная разработка ПО