Потокобезопасная очередь (список) в .net - PullRequest
13 голосов
/ 20 октября 2010

Мне нужно создать потокобезопасный список элементов, которые будут добавлены в индекс 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 ]

38 голосов
/ 20 октября 2010

Ваша реализация кажется поточно-ориентированной, хотя вам потребуется также необходимо заблокировать при чтении из items - вы не можете безопасно читать, если есть одновременная операция Add. Если вы когда-нибудь перечислите, вам нужно будет также обойти это, и это будет жить столько же времени, сколько перечислитель.

Если вы можете использовать .net 4, я настоятельно рекомендую посмотреть на пространство имен System.Collections.Concurrent . Он имеет несколько хорошо протестированных и довольно производительных коллекций, которые являются поточно-ориентированными и фактически оптимизированы для многопоточного доступа.

4 голосов
/ 20 октября 2010

Нужно ли блокировать даже при получении предметов из внутреннего списка?

Класс List не является потокобезопасным при внесении изменений. Необходимо заблокировать, если:

  • Вы используете один экземпляр класса из нескольких потоков.
  • Содержимое списка может измениться, когда вы изменяете чтение или из списка.

Предположительно, первое верно, иначе вы бы не задавали вопрос. Второе явно верно, потому что метод Add изменяет список. Так что да, тебе это нужно.

Когда вы добавляете в свой класс метод, который позволяет вам читать элементы, необходимо также заблокировать, и, что важно, вы должны использовать такой же объект блокировки, как и в AddItem.

2 голосов
/ 20 октября 2010

Да; Хотя извлечение не является внутренней небезопасной операцией, если вы также записываете в список, то вы рискуете получить его в середине записи.

Это особенно верно, если это будет работать как традиционная очередь, где извлечение фактически удалит извлеченное значение из списка.

...