【问题标题】:How to correctly access ArrayList from threadpool?如何从线程池正确访问 ArrayList?
【发布时间】:2011-07-25 11:48:42
【问题描述】:

我在我的 c# 应用程序上使用 ThreadPool,我需要在“全局”ArrayList 中添加和删除项目。线程将随时访问相同的ArrayList。我应该如何以安全的方式做到这一点?所以没有线程会同时尝试访问 ArrayList。

我正在用这个开始线程:

my_args args = new my_args(input, id, this);
ThreadPool.QueueUserWorkItem(new WaitCallback(generateKeywords), args);

【问题讨论】:

    标签: c# multithreading thread-safety threadpool


    【解决方案1】:

    您可以尝试使用带有数组作为参数的 lock 语句:

    lock(myArray){
    //do what you want, your array will be protected in this block of code
    }
    

    【讨论】:

    • 锁定集合是不好的做法。最好有单独的对象用于同步目的
    • 我同意使用同步对象是一种好方法,也许是最好的方法,但为什么不锁定数组呢?毕竟它也是一个对象。无论如何,使用同步对象至少是解决这个问题的一种更优雅的方法,所以,是的!使用同步对象。注意同步相同的对象。为此,您可以使用静态对象。
    • 使用单独的对象还可以防止误认为数组实际上是锁定的。此代码仅在所有线程都请求锁定时才有效。
    【解决方案2】:

    您可以围绕ArrayList 创建一个线程安全的包装器:

    ArrayList list = new ArrayList();
    ArrayList threadSafeList = ArrayList.Synchronized(list);
    

    但是请注意,即使使用同步的ArrayList,枚举列表仍然不安全。请参阅this msdn page 了解更多信息。

    我能问一下您为什么使用ArrayList 而不是通用集合吗?如果您使用列表作为队列来提供几个工作进程,并且您使用的是 .net 4.0,那么您可以使用 BlockingCollection<T> 对象。请参阅this msdn page 了解更多信息。

    【讨论】:

      【解决方案3】:

      我会使用 SyncRoot 来锁定数组。

      lock(((ICollection)myArray).SyncRoot)
      {
      
      }
      

      【讨论】:

        【解决方案4】:

        如果您有 .NET 4 可用,更好的选择是使用 System.Collections.Concurrent 中的集合之一。这些都提供了线程安全的读写,而无需显式锁定。

        (其中一些集合是无锁的,一些使用细粒度锁定,但它们都是线程安全的,您不必担心。)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-11-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-16
          • 1970-01-01
          • 1970-01-01
          • 2017-06-06
          相关资源
          最近更新 更多