ConcurrentDictionary Pitfall - Are delegates factories from GetOrAdd and AddOrUpdate synchronized?注意AddOrUpdate不是原子的(並且不能保證委託不會運行多次)。atomic addorupdate(嘗試使用併發字典寫命名更衣室)
我想實現的名稱使用併發字典一拉here鎖定實現,但在字典中不應永遠增長,像這樣:
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是原子的,上面的代碼就可以完成它的工作,並且條目將被適當地刪除。
請注意,通過鍵+ val擴展方法TryRemove(key,val)的條件刪除的使用提到了here。另外,IntObject是一個int的簡單可變對象包裝。
我有什麼選擇?是否有任何併發字典實現具有1.原子條件(關鍵和值)刪除和2. AddOrUpdate是原子的並確保委託不會運行多次?
有其他想法嗎?我希望命名的儲物櫃速度很快,但是由於無限制的鎖定名稱空間而沒有給定名稱的爭用,所以沒有內存壓力問題。據我所知,字符串通過名字鎖定interning鎖定會永遠增長,永遠不會被清理,並有其他副作用。互斥體是半緩慢的並且有各種煩惱(260個字符限制)。
你可能會使用類型爲'ConcurrentDictionary>'的字典,正如我在本答案中所述http://stackoverflow.com/a/12611341/1236734 –