Sobes.tech
Middle+

Как да реализираме Dictionary без да използваме ConcurrentDictionary?

sobes.tech AI

Отговор от 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 обикновено е предпочитан при чести операции за четене.