Синхронизация операций в .NET на примерах
lock-object. Это самый простой способ синхронизации. Мы заводим объект, который будем использовать для блокировки параллельного выполнения какого-то участка кода.
Применять стоит, когда нам нужно, чтобы какой-то участок кода в один момент времени выполнялся только одним потоком. Тут может быть любая работа с файлами, БД и другими ресурсами.
Важно понимать, что lock работает на уровне приложения, а не ОС, поэтому другое приложение может спокойно занять наш ресурс.
Еще следует помнить, что код в lock секции должен выполняться в рамках одного потока, поэтому мы не можем использовать внутри асинхронные вызовы.
Синтаксис
Mutex. Используется для ограничения доступа к ресурсу на уровне ОС.
Его может освободить только тот поток, который его занял.
Подойдет для ограничения доступа к файлам.
Синтаксис
SemaphoreSlim. Облегченная версия семафора. Сам семафор предоставляется ОС и используется для того, чтобы ограничить число одновременных пользователей ресурса.
Работает на уровне ОС.
Можем указать, сколько одновременно потоков могут работать с ресурсом. Полезно, если мы не хотим перегрузить его, например, при обращении к сетевой карте при REST-запросах.
Слим версия может быть асинхронной, что полезно для работы с файлами, к которым мы хотим ограничить доступ. На работе некоторые настройки сервисов мы храним в .json-файлах, для ограничения доступа к ним из нескольких потоков, мы используем слим версию и асинхронное ожидание.
Синтаксис
AutoResetEvent. Как и классы выше служит для синхронизации доступа к ресурсу.
Отличие в том, что позволяет управлять одним потоком из другого.
Синтаксис
Interlcoked. Служит для произведения атомарных операций.
Подходит, если есть какая-то переменная, которую мы хотим атомарно изменять.
Еще с его помощью можно поставить флаг на какую-то часть кода, которую должен выполнять какой-то из потоков, но нам не важно какой. Тогда при первом входе в метод поток будет поднимать флаг через Interlocked, а другие потоки будут выходить из метода, когда будут видеть, что флаг уже поднят.
Пример работы с флагом через Interlocked