数据结构的C#中惯用的保证互斥?
假设在C#中有一个数据结构的C#中惯用的保证互斥?,c#,locking,C#,Locking,假设在C#中有一个字典对象,多个线程正在访问和更改该对象。您希望某些操作是线程安全的 所以你需要一个互斥。在C#中,使用互斥的标准方式是: lock (someSharedObject) { // Mutual exclusion zone here. myDictionary.Add(1, "hello"); } 问题是,您仅仅依靠文档来阻止未来的程序员绕过互斥锁直接访问字典: myDictionary.Add(1, "hello"); 我希望编译器能够阻止未来的程序员使用未受
字典
对象,多个线程正在访问和更改该对象。您希望某些操作是线程安全的
所以你需要一个互斥。在C#中,使用互斥的标准方式是:
lock (someSharedObject)
{
// Mutual exclusion zone here.
myDictionary.Add(1, "hello");
}
问题是,您仅仅依靠文档来阻止未来的程序员绕过互斥锁直接访问字典:
myDictionary.Add(1, "hello");
我希望编译器能够阻止未来的程序员使用未受保护的字典
我认为有两种可能性:
LockedDictionary
),它确保锁定其成员方法,但在其他方面与字典类似字典
访问的类,以便调用者不通过保护就无法访问字典
LockedDictionary
的优点在于它对其他人来说是直观的。它还允许细粒度地控制哪些方法需要锁定以及锁定的程度。缺点是它不完全是一个字典
,因此不能将此对象传递给期望接收字典
的函数。(尽管您可以通过实现IDictionary
来接近这一点)
继续讨论第二个问题。guard类的优点在于,您可以实现IDisposable
,并像这样使用它:
class DictionaryFortress {
Dictionary<K, V> realDict;
Object lockobject;
void Lock() {
Monitor.Enter(lockobject);
return DictionaryGuard(lockobject, realDict);
}
}
class DictionaryGuard : IDisposable {
public Dictionary<K, V> Dict {
get { return realDict; }
}
public void Dispose() {
Monitor.Exit(lockobject);
}
}
// in some class
DictionaryFortress dict = new DictionaryFortress(); // early on
// in a function, when we need to access dictionary contents...
using (DictionaryGuard guard = dict.Lock()) {
Dictionary<K, V> actualDict = guard.Dict;
// now you can pass actualDict anywhere; no one has to know that it's locked
}
类字典fortress{
词典;
对象锁定对象;
无效锁(){
Monitor.Enter(锁定对象);
返回字典Guard(lockobject,realDict);
}
}
类字典Guard:IDisposable{
公共词典词典{
获取{return realDict;}
}
公共空间处置(){
监视器。退出(锁定对象);
}
}
//在某个班级
DictionaryFortress dict=新DictionaryFortress();//早期
//在函数中,当我们需要访问字典内容时。。。
使用(DictionaryGuard guard=dict.Lock()){
Dictionary actualDict=guard.Dict;
//现在,您可以在任何地方传递ActualAct;没有人必须知道它已锁定
}
当然,好处是我们可以访问原始字典,因此我们不受如何使用它以及在哪里传递它的限制。缺点是使用它会带来更多的开销。用户还可以在可用时保存对guard.Dict
的引用,然后在释放DictionaryGuard后使用它
我倾向于#2。我是否错过了任何有利和不利因素?有没有更好的方法来保护对我的字典的访问,同时最大限度地减少误用的风险?同样,我的要求是健忘或粗心的程序员不能跳过锁定阶段。我的愿望是它既地道、方便又灵活。你考虑过吗?它和另一个是在.NET4.0中引入的
表示线程安全的键/值对集合,可以
由多个线程并发访问
您是否考虑过?或其他线程安全集合的ConcurrentBag、ConcurrentQueue和ConcurrentStack。再发明轮子也没有意义了…谢谢你。虽然我知道我肯定是在重新发明轮子,但我忘记了这些东西的存在。你能把这个作为建议的答案吗?完成了。它是在.NET4.0中引入的。