Mutltithread:在许多情况下写入公共列表需要锁定?

时间:2009-10-21 06:12:57

标签: c# winforms multithreading

起初我认为我确实需要写锁,但我不确定(没有多少经验)如果我不使用它。

在服务器端,每个连接的客户端都有客户端类。每个类都包含公共列表,其他每个类都可以写入。客户端请求通过线程池工作项处理。

class client 
{
public List <string> A;

someEventRaisedMethod(param)
{
 client OtherClient=GetClientByID(param) //selects client class by ID sent by msg sender
 OtherCLient.A.Add("blah"); 
}

}

如果两个实例引用同一个客户端并且都尝试OtherCLient.A.Add(“blah”)怎么办?不是这里的一些作家锁吗?它适用于我,但我遇到一些我认为是由此引起的奇怪问题。

谢谢!

3 个答案:

答案 0 :(得分:2)

(更新:一如既往,Eric Lippert及时blog entry

如果您不使用锁定,则可能会丢失数据,状态损坏,可能会出现奇怪的Exception - 但偶尔会出现 ,因此非常难以调试。< / p>

你绝对需要在这里进行同步。我会在客户端上公开一个锁(所以我们可以跨越多个操作):

lock(otherClient.LockObject) {
    otherClient.A.Add("blah");
}

您可以在Add上制作同步otherClient方法,但跨越多个通常很有用 - 可能仅在缺少时检查Contains然后Add


只是澄清2点:

  • 所有访问列表(甚至是读取)也必须使用lock;否则它不起作用
  • LockObject应该是只读参考类型

第二个,也许是:

private readonly object lockObject = new object();
public object LockObject {get {return lockObject;}}

答案 1 :(得分:0)

从我的观点来看,你应该做到以下几点:

  • 将列表隔离到一个单独的类中,该类实现IList接口或仅实现您需要的子集
  • 在列表类的方法中添加对私有对象的锁定或使用ReaderWriterSlim实现 - 因为它是孤立的,只需要一个地方来更改一个单独的类

答案 2 :(得分:0)

我不知道C#的内部结构,但我记得有一段时间回顾一下java示例,如果正在读取集合的同时正在对集合进行插入(我认为它是一个哈希表),所以请确保你使用多个线程来锁定读写。 Marc Gravell是正确的,你应该创建一个全局锁来处理这个,因为它听起来你的音量相当低。

ReaderWriterLockSlim也是一个很好的选择,如果你做了很多阅读并且只做了一些写/更新动作。