private TType GetFromFirstLevel(T id, Func <T, TType> value, bool withLock) { var flc = GetFirstLevelCache(); bool added = false; var element = flc.GetOrAdd(id, k => { added = true; var t = new TElementType { Element = value(k) }; return(t); }); Debug.Assert(element != null, "element!=null"); if (added) { if (flc.Count > MaxItemsInLevel1ToActivateFlush && !Settings.NoCacheGarbageChecking) { _lowItemsCountFixing = null; } return(element.Element); } try { if (withLock) { _lock.EnterWriteLock(); } if (flc.ContainsKey(id))//если из двух потоков пытается взять один и тот же ключ, //то к этому моменту они оба попытаются добавить ключ в кэш2. //Но это можно отследить, т.к. первый записавший удаляет ключ из кэша1. { _secondLevelCache.Add(id, element); TElementType removedElement; flc.TryRemove(id, out removedElement); } return(element.Element); } finally { if (withLock) { _lock.ExitWriteLock(); } } }