Sobes.tech
Middle+
192
questionbank

Как реализовать Dictionary так, чтобы не использовать ConcurrentDictionary?

Answer from AI

sobes.tech AI

Для реализации потокобезопасного Dictionary без использования ConcurrentDictionary можно применять синхронизирующие примитивы из пространства имен System.Threading.

Основные подходы:

  1. Блокировка всего словаря (lock): Оборачивать все операции чтения и записи в блок lock с использованием одного и того же объекта синхронизации.

    // Объект для синхронизации доступа к словарю
    private readonly object _lockObject = new object();
    private readonly Dictionary<TKey, TValue> _dictionary = new Dictionary<TKey, TValue>();
    
    public void AddOrUpdate(TKey key, TValue value)
    {
        lock (_lockObject)
        {
            if (_dictionary.ContainsKey(key))
            {
                _dictionary[key] = value;
            }
            else
            {
                _dictionary.Add(key, value);
            }
        }
    }
    
    public bool TryGetValue(TKey key, out TValue value)
    {
        lock (_lockObject)
        {
            return _dictionary.TryGetValue(key, out value);
        }
    }
    
    public bool TryRemove(TKey key, out TValue value)
    {
        lock (_lockObject)
        {
            if (_dictionary.TryGetValue(key, out value))
            {
                _dictionary.Remove(key);
                return true;
            }
            return false;
        }
    }
    

    Плюсы: Простая реализация. Минусы: Низкая производительность при высокой конкуренции, так как блокируется доступ ко всему словарю даже при операциях чтения.

  2. Использование ReaderWriterLockSlim: Позволяет разделить блокировки для операций чтения и записи. Несколько потоков могут одновременно читать, но только один поток может писать.

    private readonly ReaderWriterLockSlim _lockSlim = new ReaderWriterLockSlim();
    private readonly Dictionary<TKey, TValue> _dictionary = new Dictionary<TKey, TValue>();
    
    public void AddOrUpdate(TKey key, TValue value)
    {
        _lockSlim.EnterWriteLock();
        try
        {
            if (_dictionary.ContainsKey(key))
            {
                _dictionary[key] = value;
            }
            else
            {
                _dictionary.Add(key, value);
            }
        }
        finally
        {
            _lockSlim.ExitWriteLock();
        }
    }
    
    public bool TryGetValue(TKey key, out TValue value)
    {
        _lockSlim.EnterReadLock();
        try
        {
            return _dictionary.TryGetValue(key, out value);
        }
        finally
        {
            _lockSlim.ExitReadLock();
        }
    }
    
    public bool TryRemove(TKey key, out TValue value)
    {
        _lockSlim.EnterWriteLock();
        try
        {
            if (_dictionary.TryGetValue(key, out value))
            {
                _dictionary.Remove(key);
                return true;
            }
            return false;
        }
        finally
        {
            _lockSlim.ExitWriteLock();
        }
    }
    

    Плюсы: Лучшая производительность по сравнению с lock при интенсивных операциях чтения. Минусы: Более сложная реализация, чем с простым lock.

Выбор между этих подходов зависит от специфики использования словаря, соотношения операций чтения и записи, и требуемой производительности. ReaderWriterLockSlim обычно предпочтительнее при частых операциях чтения.