Sobes.tech
Middle+

Wie implementiert man ein Dictionary, ohne ConcurrentDictionary zu verwenden?

sobes.tech KI

Antwort von AI

Um einen Dictionary threadsicher zu implementieren, ohne ConcurrentDictionary zu verwenden, können Synchronisationsprimitive aus dem Namespace System.Threading verwendet werden.

Hauptansätze:

  1. Gesamtes Wörterbuch sperren (lock): Alle Lese- und Schreiboperationen in einen lock-Block einschließen, der dasselbe Synchronisationsobjekt verwendet.

    // Objekt zur Synchronisierung des Zugriffs auf das Wörterbuch
    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;
        }
    }
    

    Vorteile: Einfache Implementierung. Nachteile: Geringe Leistung bei hoher Konkurrenz, da der Zugriff auf das gesamte Wörterbuch auch bei Leseoperationen blockiert wird.

  2. Verwendung von ReaderWriterLockSlim: Ermöglicht die Trennung der Sperren für Lese- und Schreiboperationen. Mehrere Threads können gleichzeitig lesen, aber nur ein Thread kann schreiben.

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

    Vorteile: Bessere Leistung im Vergleich zu lock bei intensiven Leseoperationen. Nachteile: Komplexere Implementierung als mit einfachem lock.

Die Wahl zwischen diesen Ansätzen hängt von der Nutzung des Wörterbuchs, dem Verhältnis von Lese- zu Schreiboperationen und den Leistungsanforderungen ab. ReaderWriterLockSlim ist bei häufigen Leseoperationen in der Regel vorzuziehen.