Для чего нужен SlimLock (ReaderWriterLockSlim) в C#?

«Для чего нужен SlimLock (ReaderWriterLockSlim) в C#?» — вопрос из категории Многопоточность, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Ключевые преимущества перед lock или Monitor:

  • Повышенный параллелизм: Множество потоков-читателей не блокируют друг друга.
  • Меньшие накладные расходы: Оптимизированная реализация по сравнению со старым ReaderWriterLock.

Типичный сценарий использования — кэш в памяти:

private readonly ReaderWriterLockSlim _cacheLock = new ReaderWriterLockSlim();
private Dictionary<string, Data> _cache = new Dictionary<string, Data>();

public Data GetOrAdd(string key)
{
    // 1. Пытаемся войти в режим чтения (не блокирует других читателей)
    _cacheLock.EnterReadLock();
    try
    {
        if (_cache.TryGetValue(key, out Data cachedData))
        {
            return cachedData;
        }
    }
    finally
    {
        _cacheLock.ExitReadLock();
    }

    // 2. Если данных нет, переходим в режим записи (эксклюзивный доступ)
    _cacheLock.EnterWriteLock();
    try
    {
        // Двойная проверка на случай, если другой поток уже добавил значение
        if (!_cache.TryGetValue(key, out Data cachedData))
        {
            cachedData = LoadDataFromSource(key); // Дорогая операция
            _cache[key] = cachedData;
        }
        return cachedData;
    }
    finally
    {
        _cacheLock.ExitWriteLock();
    }
}

Важные правила:

  • Всегда освобождайте блокировку в блоке finally.
  • Избегайте перехода из режима чтения в режим записи в одном потоке (это может привести к взаимоблокировке). Используйте EnterUpgradeableReadLock() для таких случаев.
  • Используйте ReaderWriterLockSlim только когда профиль доступа "частое чтение / редкая запись" — в противном случае обычный lock может быть эффективнее.