Неблокирующая коллекция локов с функцией самоочистки
От: LWhisper  
Дата: 11.08.16 13:24
Оценка: :)
Всем привет.
Подскажите — как можно оптимизировать следующий код?
Класс предоставляет локи для синхронизации операций в других Concurrent-коллекциях. Например, в ConcurrentDictionary для методов с отложенной инициализации AddOrUpdate и GetOrAdd.
Задача — получить объект блокировки (который SyncRoot) для определенного ключа (чтобы не блокировать всю коллекцию). Если больше никто эту блокировку не использует — убрать из коллекции. Идеально было бы вовсе отдать работу по подсчёту ссылок GC.

    public sealed class ConcurrentLockProvider<TKey>
    {
        private readonly Dictionary<TKey, Lock> _locks;

        public ConcurrentLockProvider()
            : this(EqualityComparer<TKey>.Default)
        {
        }

        public ConcurrentLockProvider(IEqualityComparer<TKey> comparer)
        {
            _locks = new Dictionary<TKey, Lock>(comparer);
        }

        public IDisposable Acquire(TKey key)
        {
            lock(_locks)
            {
                Lock item;
                if(!_locks.TryGetValue(key, out item))
                {
                    item = new Lock(key, _locks);
                    _locks[key] = item;
                }
                Interlocked.Increment(ref item.Counter);
                return item;
            }
        }

        private sealed class Lock : IDisposable
        {
            private readonly TKey _key;
            private readonly Dictionary<TKey, Lock> _dic;
            
            public long Counter;

            public Lock(TKey key, Dictionary<TKey, Lock> locks)
            {
                _key = key;
                _dic = locks;
            }

            #region Implementation of IDisposable

            public void Dispose()
            {
                lock(_dic)
                {
                    if(Interlocked.Decrement(ref Counter) < 1)
                        _dic.Remove(_key);
                }
            }

            #endregion
        }
    }
gc lock collection c# .net threading concurrency
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.