我是否需要在以下简单的字典的getter和setter中使用一些线程安全机制?
如果需要,请输入lock和ConcurrentDictionary的示例。
public virtual void Add(IFoo foo)
{
dictionary.Add(foo.name, foo);
}
public virtual IFoo Get(string name)
{
if (!dictionary.TryGetValue(name, out IFoo foo)) return null;
return foo;
}
public virtual bool Has(string name)
{
return dictionary.TryGetValue(name, out IFoo foo);
}
public virtual IFoo Remove(string name)
{
if (dictionary.TryGetValue(name, out IFoo foo))
{
dictionary.Remove(name);
}
return foo;
}
protected readonly IDictionary<string, IFoo> dictionary = new Dictionary<string, IFoo>();
答案 0 :(得分:1)
根据要求,这是一个使用锁的线程安全版本。您的Add方法可以调用GetOrAdd
或AddOrUpdate
,具体取决于您是想在争用时“先赢一局”还是“最后一场胜利”。
public virtual void Add(IFoo foo)
{
AddOrUpdate(foo); // If you want "last one wins"
//GetOrAdd(foo); // If you want "first one wins"
}
private virtual IFoo GetOrAdd(IFoo foo)
{
lock(dictionary)
{
IFoo result;
if (!dictionary.TryGetValue(foo.name, out result))
{
// Not in the dictionary; add it
result = foo;
dictionary.Add(foo.name, foo);
}
return result;
}
}
public virtual void AddOrUpdate(IFoo foo)
{
lock(dictionary)
{
// Last one wins and overwrites if there is a race-condition
dictionary[foo.name] = foo;
}
}
public virtual IFoo Get(string name)
{
lock(dictionary)
{
IFoo foo;
dictionary.TryGetValue(name, out foo);
return foo; // will be null if TryGetValue returned false
}
}
public virtual bool Has(string name)
{
lock(dictionary)
{
return dictionary.ContainsKey(name);
}
// But there's no guarantee it's still there when this method returns
}
public virtual IFoo Remove(string name)
{
lock (dictionary)
{
IFoo result;
if (dictionary.TryGetValue(name, out result))
{
dictionary.Remove(name);
}
return result;
}
}
// Dictionary should be private, not protected to be sure a derived
// class doesn't access it without using locks
private readonly IDictionary<string, IFoo> dictionary = new Dictionary<string, IFoo>();
这是ConcurrentDictionary的一个版本:
public virtual void Add(IFoo foo)
{
AddOrUpdate(foo); // If you want "last one wins"
//GetOrAdd(foo); // If you want "first one wins"
}
private virtual IFoo GetOrAdd(IFoo foo)
{
return concurrentDictionary.GetOrAdd(foo.name, foo);
}
public virtual void AddOrUpdate(IFoo foo)
{
concurrentDictionary[foo.name] = foo;
}
public virtual IFoo Get(string name)
{
IFoo result;
concurrentDictionary.TryGetValue(name, out result);
return result; // will be null if TryGetValue returned false
}
public virtual bool Has(string name)
{
return concurrentDictionary.ContainsKey(name);
// But there's no guarantee it's still there when this method returns
}
public virtual IFoo Remove(string name)
{
IFoo result;
concurrentDictionary.TryRemove(name, out result);
return result;
}
private readonly ConcurrentDictionary<string, IFoo> concurrentDictionary = new ConcurrentDictionary<string, IFoo>();
答案 1 :(得分:0)
如果您的词典将从不同的主题访问,那么您应该阅读以下有关词典的内容:
只要不修改集合,词典就可以同时支持多个阅读器。即便如此,通过集合枚举本质上不是一个线程安全的过程。在枚举与写访问争用的极少数情况下,必须在整个枚举期间锁定该集合。要允许多个线程访问集合以进行读写,您必须实现自己的同步。
我建议使用ConcurrentDictionary<TKey, TValue>
作为线程安全的集合,它提供原子和线程安全的方法:
所有这些操作都是原子的,并且对于ConcurrentDictionary类的所有其他操作都是线程安全的。唯一的例外是接受委托的方法,即AddOrUpdate和GetOrAdd。
点击此链接:https://msdn.microsoft.com/en-us/library/dd287191(v=vs.110).aspx
而不是使用自己的锁定代码,但您可以使用lock
语句
如果您想使用Dictionary
来实现线程同步,请查看以下链接:https://msdn.microsoft.com/en-us/library/c5kehkcz.aspx