Обзор вопросов по языка програмиированию 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 и SemaphoreSlimSemaphore sem = new Semaphore(2, 5); // максимум 2 потока одновременно
sem.WaitOne();
// критическая секция
sem.Release();
Поддерживает асинхронные методы:
WaitAsync()Отличие от обычного Semaphore:
AutoResetEvent и ManualResetEventAutoResetEvent
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✨