Sobes.tech
Middle+

Hoe implementeer je een Dictionary zonder ConcurrentDictionary te gebruiken?

sobes.tech AI

Antwoord van AI

Om een thread-veilige Dictionary te implementeren zonder ConcurrentDictionary te gebruiken, kun je synchronisatie-primitieven uit de namespace System.Threading gebruiken.

Belangrijkste benaderingen:

  1. Het hele woordenboek blokkeren (lock): Omring alle lees- en schrijfbewerkingen met een lock-blok dat hetzelfde synchronisatie-object gebruikt.

    // Object voor synchronisatie van toegang tot het woordenboek
    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;
        }
    }
    

    Voordelen: Eenvoudige implementatie. Nadelen: Lage prestaties bij hoge gelijktijdigheid, omdat toegang tot het hele woordenboek wordt geblokkeerd, zelfs bij leesbewerkingen.

  2. Gebruik van ReaderWriterLockSlim: Hiermee kunnen lees- en schrijfsleutels worden gescheiden. Meerdere threads kunnen gelijktijdig lezen, maar slechts één schrijven.

    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();
        }
    }
    

    Voordelen: Betere prestaties in vergelijking met lock bij intensieve leesbewerkingen. Nadelen: Complexere implementatie dan met een eenvoudige lock.

De keuze tussen deze benaderingen hangt af van de aard van het gebruik van het woordenboek, de verhouding tussen lees- en schrijfbewerkingen, en de prestatiewensen. ReaderWriterLockSlim wordt meestal aanbevolen voor frequente leesbewerkingen.