Потоковая безопасная очередь (список) в .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.

Спасибо Бен

Ответ 1

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

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

Ответ 2

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

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

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

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

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

Ответ 3

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

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