Sobes.tech
Middle+

Comment implémenter un Dictionary sans utiliser ConcurrentDictionary?

sobes.tech IA

Réponse de l'IA

Pour implémenter un Dictionary thread-safe sans utiliser ConcurrentDictionary, vous pouvez utiliser des primitives de synchronisation du namespace System.Threading.

Approches principales:

  1. Verrouillage de tout le dictionnaire (lock): Envelopper toutes les opérations de lecture et d'écriture dans un bloc lock utilisant le même objet de synchronisation.

    // Objet pour synchroniser l'accès au dictionnaire
    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;
        }
    }
    

    Avantages: Implémentation simple. Inconvénients: Faible performance en haute concurrence, car l'accès à tout le dictionnaire est bloqué même lors des opérations de lecture.

  2. Utilisation de ReaderWriterLockSlim: Permet de séparer les verrouillages pour les opérations de lecture et d'écriture. Plusieurs threads peuvent lire simultanément, mais un seul peut écrire.

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

    Avantages: Meilleure performance par rapport à lock lors d'opérations de lecture intensives. Inconvénients: Implémentation plus complexe qu'avec un simple lock.

Le choix entre ces approches dépend de la nature de l'utilisation du dictionnaire, de la proportion d'opérations de lecture et d'écriture, et des exigences de performance. ReaderWriterLockSlim est généralement préféré pour des opérations de lecture fréquentes.