【问题标题】:How lock work for static collection锁定如何用于静态收集
【发布时间】:2017-03-10 13:20:50
【问题描述】:

lock关键字用于你想实现该区域最多由线程执行的地方,在多线程环境中,其余线程将等待该区域。

我有一个集合IList<Student> student=new List<Student>() 正在多个类中使用。

在某些地方,对象被添加到列表中,而在某些地方,对象被删除。这会导致一些不一致的行为。

当我在多线程环境中锁定类 x 中的集合时,是否会为所有类锁定该集合,并且不同类中的所有线程都会等待锁定?

Class StaticClass
{
 Public static IList<Student> student=new List<Student>();
} 


Class ClassA
{
 //add an item in the collection
} 

Class ClassB 
{
 //delete an item in the collection
} 

Class ClassC
{
//lock the collection here 

        lock (StaticClass.student)
        {

          foreach (ConnectionManager con in ConnectionManager.GetAllStudents())
          {
            con.Send(offlinePresence);
          }
        }

}

当我将集合锁定在 ClassC 中时,classA 和 ClassB 的其他线程会等待吗?直到 for 循环执行没有人被允许添加或删除集合中的项目,因为集合已被锁定?

【问题讨论】:

  • 基本上是的,但是最好有一个单独的static readonly object 用于锁定而不是使用列表(或创建列表readonly),以便在锁定时不能更改引用的对象
  • For 循环您可以创建列表的副本(新实例),然后在循环期间添加、删除类不会影响。 foreach(var student in students.ToList())...
  • 您必须使用lock EVERYWHERE...每次您访问该集合以任何方式您必须锁定它。 StaticClass.student.Count? lockStaticClass.student[0]? lock!
  • 有关@slawekwin 评论的更多信息,请参见stackoverflow.com/questions/251391/why-is-lockthis-bad

标签: c# multithreading locking


【解决方案1】:

查看来自System.ServiceModel.dll 程序集的System.Collections.Generic.SynchronizedCollection&lt;T&gt;。所有锁定的东西都是内置的。

正如 Fabio 所说,ConcurrentBag 也可以工作,但是会为每个访问它的线程创建一个单独的列表上下文。当您尝试删除项目时,它就像一个队列一样工作。一旦您用完自己线程列表中的项目,它就会从其他线程的列表中“窃取”项目(以线程安全的方式)。

对于您的任务,我猜 SynchronizedCollection 会更好。

【讨论】:

    【解决方案2】:

    当您的代码获取对象上的锁时,它不会阻止其他线程对该对象的访问。这个对象唯一发生的事情是,只要锁没有被释放,其他线程就无法获取同一个对象的锁。

    通常的做法是保留一个单独的普通对象作为锁的目标。

    在您的示例中,只要代码没有首先明确锁定它,其他线程仍然可以访问 List&lt;Student&gt; 对象。

    锁定会导致严重的性能问题(线程相互等待),并且在许多情况下不需要显式实现。看看 .NET Framework 的 Concurrent 集合类即可。

    【讨论】:

      猜你喜欢
      • 2018-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-06
      • 2012-10-30
      • 1970-01-01
      相关资源
      最近更新 更多