【问题标题】:Thread safe queue (list) in .net.net 中的线程安全队列(列表)
【发布时间】:2011-04-28 02:22:59
【问题描述】:

我需要创建要添加到 lucene 索引的项目的线程安全列表。

下面的线程安全吗?

public sealed class IndexQueue
{
    static readonly IndexQueue instance = new IndexQueue();
    private List<string> items = new List<string>();

    private IndexQueue() { }

    public static IndexQueue Instance {
        get { return instance; }
    }

    private object padlock = new object();

    public void AddItem(string item) {
        lock (padlock) {
            items.Add(item);
        }
    }
}

即使从内部列表中获取项目也需要锁定吗?

我们的想法是,然后我们将运行一个单独的任务来从 indexqueue 中获取项目并将它们添加到 lucene 索引中。

谢谢 本

【问题讨论】:

  • .NET 4 中有线程安全的实现(如果您甚至可以使用 4),不确定您是否知道,因为我看到您正在滚动自己...msdn.microsoft.com/en-us/library/…
  • 谢谢大家。将看看 System.Collections.Concurrent
  • 我不认为System.Collections.Concurrent 对你有用。没有List 等效项,即使有,您仍可能需要应用自己的锁定以使项的枚举成为原子的。这实际上取决于您希望枚举如何被多个线程感知。
  • Brian - ConcurrentQueue 正是我们所需要的。它的先进先出行为对我们有用。但是,正如您所说的那样,我们确实需要在对 Contains 的调用周围引入锁,以防止将重复项添加到队列中 - 只是为了防止发生竞争条件。

标签: c# multithreading thread-safety lucene.net


【解决方案1】:

即使从内部列表中获取项目也需要锁定吗?

当您进行修改时,List 类不是线程安全的。在以下情况下需要锁定:

  • 您使用来自多个线程的类的单个实例。
  • 当您修改从列表中读取时,列表的内容可能会发生变化。

大概第一个是真的,否则你不会问这个问题。第二个显然是正确的,因为Add 方法修改了列表。所以,是的,你需要它。

当你向你的类添加一个允许你读回项目的方法时,它也需要锁定,重要的是你必须使用 same 锁定对象,就像你在AddItem 中所做的那样。

【讨论】:

    【解决方案2】:

    您的实现似乎是线程安全的,尽管您在从items 读取时也需要锁定 - 如果存在并发 Add 操作,您将无法安全读取。如果你曾经枚举,你也需要锁定它,并且它需要和枚举器一样长。

    如果您可以使用 .net 4,我强烈建议您查看 System.Collections.Concurrent 命名空间。它有一些经过良好测试且性能相当不错的集合,这些集合是线程安全的,实际上围绕多线程访问进行了优化。

    【讨论】:

      【解决方案3】:

      是的;虽然检索本质上不是不安全操作,但如果您也在写入列表,那么您将面临在写入过程中检索的风险。

      如果这将像传统队列一样运行,则尤其如此,其中检索实际上会从列表中删除检索到的值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-12-26
        • 2014-03-13
        • 2012-11-05
        • 2010-10-22
        • 1970-01-01
        • 2023-03-04
        • 1970-01-01
        相关资源
        最近更新 更多