如何在 IList 上使用锁

the*_*ghn 1 c# multithreading

我有一个实现 IList 接口的静态集合。该集合在整个应用程序中使用,包括添加/删除项目。

由于多线程问题,我想知道我可以做些什么来确保列表一次修改一个,例如当 1 个线程尝试添加一项时,另一个线程当时不应该删除一项。

我想知道 lock(this) 和 lock(privateObject) 之间有什么区别?对于我的情况,哪一个更好?

谢谢。

Sco*_*man 5

lock(this)锁定整个实例,而lock(privateObject)仅锁定特定的实例变量。第二个是更好的选择,因为锁定整个实例将阻止其他线程对该对象执行任何操作。

\n\n

来自MSDN

\n\n
\n

一般来说,避免锁定公共类型或超出代码控制范围的实例。常见构造 lock\n (this)、lock (typeof (MyType)) 和 \n lock ("myLock") 违反了此\n 准则:

\n\n
    \n
  • 如果可以公开访问实例,\n 锁(this)就会出现问题。

  • \n
  • 如果\n MyType 可公开访问,lock (typeof (MyType)) 就会出现问题。

  • \n
  • lock(\xe2\x80\x9cmyLock\xe2\x80\x9d) 是一个问题,因为进程中使用相同字符串的任何其他代码都将共享相同的锁。

  • \n
\n\n

最佳实践是定义要锁定的私有对象,或定义私有静态对象变量来保护所有实例共有的数据。

\n
\n\n

在这种特殊情况下,集合是静态的,这实际上意味着有一个实例,但这仍然不会改变 和 的lock(this)行为lock(privateObject)方式。

\n\n

lock(this)即使在静态集合中使用,您仍然会锁定整个实例。在这种情况下,一旦线程 A 获取了方法的锁,Foo()所有其他线程都必须等待才能对集合执行任何操作。

\n\n

使用lock(privateObject)意味着一旦线程 A 获取了方法的锁,Foo()所有其他线程都可以执行任何其他操作,除非Foo()等待。只有当另一个线程尝试执行方法时,Foo()它才必须等待,直到线程 A 完成其Foo()操作并释放锁。

\n