Не потокобезопасен - общедоступный статический список <T> - PullRequest
0 голосов
/ 20 ноября 2011

Я читал в MSDN, что List является поточно-ориентированным при использовании в качестве публичного статического типа.Однако следующий фрагмент кода доказывает обратное.Я пытаюсь добавить и удалить элементы из списка, но метод remove выдает ошибку посередине, говоря, что индекс выходит за границы.Что здесь не так?

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

class Program
{
    public static List<string> strlist = new List<string>();
    public static AutoResetEvent autoEvent = new AutoResetEvent(false);
    static void Main(string[] args)
    {

        strlist = new List<string>();
        new Thread(() => 
        {

            for(int i=0;i<10000000;i++)
            {
         strlist.Add("item1");
            }
            //Thread.Sleep(5000);
            autoEvent.Set();
        }).Start(); ;

        new Thread(() => {

         strlist.ForEach(e => strlist.Remove(e));

        }).Start();

        Console.WriteLine("Waiting");
        autoEvent.WaitOne();
        int ci = 0;

        strlist.ForEach(str => ci++);
        Console.WriteLine(ci.ToString() + " Done");
        Console.Read();


    }

}

Ответы [ 3 ]

12 голосов
/ 20 ноября 2011

Я читал в MSDN, что List является поточно-ориентированным при использовании в качестве открытого статического типа.

Это утверждение неверно.Вы, вероятно, ссылаетесь на этот текст:

Открытые статические члены этого типа являются поточно-ориентированными.

Это относится к членам класса List<T>. не относится к экземплярам класса List<T>.

9 голосов
/ 20 ноября 2011

Ваше чтение было неверным. Вы используете элементы экземпляра (.Add() и т. Д.); члены экземпляра не потокобезопасны; MSDN явно об этом.

Резьба безопасности

Открытые статические (Shared в Visual Basic) члены этого типа являются поточно-ориентированными. Любые члены экземпляра не гарантированно являются потокобезопасными.

A List<T> может поддерживать несколько считывателей одновременно, если коллекция не изменена. Перечисление через коллекцию по сути не является потокобезопасной процедурой. В редком случае, когда перечисление конкурирует с одним или несколькими доступами на запись, единственный способ обеспечить безопасность потока - заблокировать коллекцию в течение всего перечисления. Чтобы обеспечить доступ к коллекции из нескольких потоков для чтения и записи, необходимо реализовать собственную синхронизацию.

Фактически, List<T> не имеет каких-либо статических методов (текст просто утверждает значение по умолчанию: статические члены обычно являются поточно-ориентированными; элементы экземпляра обычно не являются потоко-безопасными)

1 голос
/ 20 ноября 2011

Я думаю, что когда они сказали "статический", они не имели в виду, что вы должны использовать ключевое слово static , и все работает. Они имели в виду, что пока список статичен, как, например, «он никогда не изменяется каким-либо образом», вы можете без проблем использовать его из нескольких потоков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...