.net中的线程安全队列(列表)

时间:2010-10-20 14:36:53

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

我需要创建一个线程安全的项目列表,添加到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索引中。

由于 本

3 个答案:

答案 0 :(得分:38)

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

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

答案 1 :(得分:4)

  

即使从内部列表中获取项目,是否还需要锁定?

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

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

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

当您向类中添加一个允许您回读项目的方法时,还需要锁定,重要的是,您必须使用相同锁定对象,就像在{{1}中一样}。

答案 2 :(得分:2)

是;虽然检索不是一个本质上不安全的操作,但如果你也写入列表,那么你就有可能在写入过程中检索。

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