a> отмечает, что AddOrUpdate не является атомарным (и не может гарантировать, что делегаты не будут запускаться более одного раза).
Я пытаюсь реализовать реализацию блокировки имен, используя параллельный словарь a la здесь, но там, где словарь не должен расти вечно, например:
public class ConcurrentDictionaryNamedLocker : INamedLocker
{
// the IntObject values serve as the locks and the counter for how many RunWithLock jobs
// are about to enter or have entered the critical section.
private readonly ConcurrentDictionary<string, IntObject> _lockDict = new ConcurrentDictionary<string, IntObject>();
private static readonly IntObject One = new IntObject(1);
private readonly Func<string, IntObject, IntObject> _decrementFunc = (s, o) => o - 1;
private readonly Func<string, IntObject, IntObject> _incrementFunc = (s, o) => o + 1;
private readonly Func<string, IntObject> _oneFunc = s => new IntObject(1);
private readonly Func<string, IntObject> _zeroFunc = s => new IntObject(0);
public TResult RunWithLock<TResult>(string name, Func<TResult> body)
{
name = name.ToLower();
TResult toReturn;
lock (_lockDict.AddOrUpdate(name, _oneFunc, _incrementFunc))
{
toReturn = body();
if (!_lockDict.TryRemove(name, One))
_lockDict.AddOrUpdate(name, _zeroFunc, _decrementFunc);
}
return toReturn;
}
public void RunWithLock(string name, Action body)
{
name = name.ToLower();
lock (_lockDict.AddOrUpdate(name, _oneFunc, _incrementFunc))
{
body();
if (!_lockDict.TryRemove(name, One))
_lockDict.AddOrUpdate(name, _zeroFunc, _decrementFunc);
}
}
}
Но проблема в том, что AddOrUpdate не является атомарным, поэтому я вижу, что часто записи не удаляются при возникновении разногласий. Однако я почти уверен, что если бы AddOrUpdate был атомарным, приведенный выше код выполнил бы свою работу, и записи были бы удалены соответствующим образом.
Обратите внимание на использование условного удаления методом расширения key + val TryRemove (key, val), упомянутого в здесь. Кроме того, IntObject - это простая изменяемая объектная оболочка типа int.
Какие у меня варианты? Существуют ли какие-либо параллельные реализации словарей, которые имеют 1. атомарное условное (по ключу и значению) удаление и 2. AddOrUpdate является атомарным и гарантирует, что делегаты не запускаются более одного раза?
Есть еще идеи? Я бы хотел, чтобы именованный шкафчик был быстрым, но не имел проблем с нехваткой памяти, учитывая неограниченное пространство имен блокировки, но с небольшим количеством конфликтов по данному имени. Насколько мне известно, блокировка интернирования строк по имени постоянно растет, никогда не очищается и имеет другие побочные эффекты. А мьютексы полумедленны и имеют различные неприятности (ограничение в 260 символов).
ConcurrentDictionary<TKey, Lazy<TValue>>
, как я описал в этом ответе stackoverflow.com/a/12611341/1236734 - person JG in SD   schedule 19.05.2016