Ответ
Monitor, Mutex и Semaphore — это примитивы синхронизации в .NET для управления доступом к общим ресурсам в многопоточной среде. Их ключевые различия — в области действия (процесс/система) и количестве потоков, которым разрешен одновременный доступ.
1. Monitor (Внутрипроцессный, эксклюзивный доступ)
- Область действия: Только в пределах одного процесса (AppDomain).
- Доступ: Позволяет войти в критическую секцию только одному потоку.
- Использование: Базовый механизм для
lock. Легковесный.
private object _lockObj = new object();
void AccessResource()
{
lock (_lockObj) // Использует Monitor внутри
{
// Только один поток здесь
}
}
2. Mutex (Межпроцессный, эксклюзивный доступ)
- Область действия: Может быть системным (именованным), работая между разными процессами.
- Доступ: Позволяет войти в критическую секцию только одному потоку (или процессу). Имеет понятие "владельца".
- Использование: Для синхронизации между процессами (например, гарантия, что только один экземпляр приложения запущен).
// Именованный мьютекс для межпроцессной синхронизации
using var mutex = new Mutex(false, "Global\MyAppSingletonMutex");
if (!mutex.WaitOne(TimeSpan.FromSeconds(1))) // Таймаут для избежания deadlock
{
Console.WriteLine("Другой экземпляр приложения уже запущен.");
return;
}
try
{
// Код, выполняемый только в одном экземпляре приложения
}
finally
{
mutex.ReleaseMutex();
}
3. Semaphore (Ограничение количества потоков)
- Область действия: Может быть внутрипроцессным или именованным (межпроцессным).
- Доступ: Ограничивает не единицей, а заданным максимальным количеством потоков, которые могут одновременно войти в секцию.
- Использование: Для ограничения доступа к пулу ресурсов (например, не более 10 одновременных подключений к БД).
// Семафор, разрешающий одновременный доступ 3 потокам
private static SemaphoreSlim _pool = new SemaphoreSlim(3, 3);
async Task AccessDatabaseAsync()
{
await _pool.WaitAsync(); // Ждем, если уже 3 потока внутри
try
{
// Не более 3 потоков выполняют эту часть одновременно
await ExecuteQueryAsync();
}
finally
{
_pool.Release();
}
}
Сводная таблица
| Примитив | Область действия | Количество потоков | Ключевое назначение |
|---|---|---|---|
Monitor (lock) |
Внутри процесса | 1 | Быстрая синхронизация потоков в одном приложении. |
| Mutex | Внутри или между процессами | 1 | Эксклюзивный доступ к ресурсу для одного потока/процесса. |
| Semaphore | Внутри или между процессами | N (задается) | Ограничение пула одновременных операций (например, подключений, потоков). |
Вывод: Выбирайте Monitor/lock для простых случаев внутри одного приложения. Используйте Mutex для межпроцессной блокировки. Применяйте Semaphore или SemaphoreSlim, когда нужно ограничить не единицей, а заданным числом потоков.