Обзор вопросов по языка програмиированию C# и технологии NET
Примитивы синхронизации нужны для:
В .NET есть несколько уровней примитивов: от простых до более сложных, включая асинхронные варианты.
lock
(Monitor)private readonly object _lock = new object();
lock(_lock)
{
// критическая секция
}
Monitor.Enter
/ Monitor.Exit
.Особенности:
Monitor.Wait()
и Monitor.Pulse()
можно делать условные ожидания.Mutex
(System.Threading.Mutex)Mutex mutex = new Mutex();
mutex.WaitOne(); // захват
try
{
// критическая секция
}
finally
{
mutex.ReleaseMutex();
}
Особенности:
lock
.Semaphore
и SemaphoreSlim
Semaphore sem = new Semaphore(2, 5); // максимум 2 потока одновременно
sem.WaitOne();
// критическая секция
sem.Release();
Поддерживает асинхронные методы:
WaitAsync()
Отличие от обычного Semaphore:
AutoResetEvent
и ManualResetEvent
AutoResetEvent
ManualResetEvent
Reset()
).AutoResetEvent are = new AutoResetEvent(false);
Thread t = new Thread(() =>
{
Console.WriteLine("Waiting...");
are.WaitOne(); // ждёт сигнала
Console.WriteLine("Signaled!");
});
t.Start();
Thread.Sleep(1000);
are.Set(); // отправка сигнала
Monitor.Wait()
/ Monitor.Pulse()
/ PulseAll()
Wait()
— поток ждёт сигнала, отпуская lock.Pulse()
— сигнал одному ожидающему потоку.PulseAll()
— сигнал всем ожидающим потокам.lock(_lock)
{
while(!condition) Monitor.Wait(_lock);
// обработка
Monitor.Pulse(_lock);
}
Позволяет:
Пример:
ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
// Чтение
rwLock.EnterReadLock();
try { /* чтение */ } finally { rwLock.ExitReadLock(); }
// Запись
rwLock.EnterWriteLock();
try { /* запись */ } finally { rwLock.ExitWriteLock(); }
Методы:
Interlocked.Increment(ref x)
Interlocked.Decrement(ref x)
Interlocked.Add(ref x, value)
Interlocked.Exchange(ref x, newValue)
Interlocked.CompareExchange(ref x, newValue, comparand)
int
, long
, IntPtr
).lock vs Monitor
lock
— синтаксический сахар для Monitor.Enter/Exit
.Mutex vs Semaphore
Deadlock
Async / await
Для асинхронных методов:
SemaphoreSlim.WaitAsync()
AsyncLock
(от сторонних библиотек)lock
не совместим с await
внутри, нужен AsyncLock
.
Производительность
Interlocked
быстрее всех.lock
медленнее, но проще и безопаснее.Mutex
самый дорогой.Примитив | Scope | Особенности | Поддержка async |
---|---|---|---|
lock / Monitor | Один процесс | Рекурсивный, блокирует поток | Нет |
Mutex | Межпроцессный | Можно именовать, дорогой | Нет |
Semaphore | Один/Межпроцессный | Ограничение N потоков | Нет |
SemaphoreSlim | Один процесс | Лёгкий, поддержка async | Да |
AutoResetEvent | Один процесс | Сигнал одному потоку | Нет |
ManualResetEvent | Один процесс | Сигнал всем потокам | Нет |
ReaderWriterLockSlim | Один процесс | Много читателей, один писатель | Нет |
Interlocked | Один процесс | Атомарные операции с числами | Да (частично) |
✨Dvurechensky✨