C# 多线程:在许多情况下写入公共列表,需要锁吗?

C# 多线程:在许多情况下写入公共列表,需要锁吗?,c#,winforms,multithreading,C#,Winforms,Multithreading,起初我认为我确实需要writerlock,但我不确定(没有太多经验)如果我不使用它会怎么样 在服务器端,每个连接的客户机都有客户机类。每个类都包含每个其他类都可以写入的公共列表。客户端请求通过线程池工作项进行处理 class client { public List <string> A; someEventRaisedMethod(param) { client OtherClient=GetClientByID(param) //selects client class b

起初我认为我确实需要writerlock,但我不确定(没有太多经验)如果我不使用它会怎么样

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

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"); 
}

}
类客户端
{
公开名单A;
someEventRaisedMethod(参数)
{
client OtherClient=GetClientByID(param)//根据msg sender发送的ID选择客户机类
其他客户。A.添加(“废话”);
}
}
如果两个实例引用同一个客户端,并且都尝试OtherCLient.A.Add(“blah”)?这里不是有个作家锁吗?这对我来说是可行的,但我遇到了一些奇怪的问题,我认为这就是原因

谢谢大家!

(更新:与往常一样,埃里克·利珀特有一份及时的报告)

如果不使用锁,则可能会出现数据丢失、状态损坏以及奇怪的
异常
——但只是偶尔出现,因此很难调试

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

您可以在
otherClient
上创建一个同步的
Add
方法,但是跨越多个方法通常很有用—可能需要检查
包含的
,然后仅在缺少时添加
,等等


我只想澄清两点:

  • 对列表的所有访问(即使读取)也必须使用
    ;否则就不行了
  • LockObject
    应为只读引用类型
第二,也许:

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

在我看来,你应该做到以下几点:

  • 将列表隔离到一个单独的类中,该类实现IList接口或仅实现所需的子集
  • 要么在list类的方法中添加私有对象的锁定,要么使用ReaderWriterSlim实现——因为它是隔离的,所以在单个类中只需要一个地方进行更改
我不知道C#的内部结构,但我记得有一段时间我读过java示例,如果线程在读取集合的同时对集合进行插入(我认为它是一个哈希表),那么它可能会导致线程无休止地循环,所以请确保您使用的是多个线程,您可以同时锁定读写。Marc Gravell是正确的,您应该创建一个全局锁来处理这个问题,因为听起来您的音量相当低


ReaderWriterLockSlim也是一个不错的选择,如果你做了大量的阅读,并且只做了一些写/更新操作。

谢谢!你是对的,我没有遇到任何异常,但有时我真的错过了数据。你提到的锁码够了吗?我这样问是因为我根本没有使用锁的经验;您可以使用更细粒度的读写器锁,但要保持简单-*特别是如果您是新手<代码>锁定
是最容易摸索的方法。(另请参见我澄清的一些要点)
private readonly object lockObject = new object();
public object LockObject {get {return lockObject;}}