У меня есть вопрос о безопасности потоков коллекции List<T>
.
Вот мой тестовый класс:
Test t = new Test();
t.a = 100;
t.b = 20;
t.c = 10;
Затем скажем, что 10 экземпляров выше были созданы и добавлены в Список, как показано ниже.
List<Test> tCollection = new List<Test>();
tCollection.add(t);
Позже я повторяю объекты теста в tCollection
.
foreach(Test t in tCollection)
{
// do calculation
}
Является ли добавление объектов в List<Test>
и итерация через List<Test>
безопасна потоком?
По умолчанию.net-коллекции не являются потокобезопасными.
Это означает, что они не содержат дополнительного кода, который имеет дело с многопоточным доступом, поскольку такой код снизит их производительность в однопоточных сценариях.
Как сказал Александр Галкин в другом ответе, Microsoft предоставляет некоторые коллекции, специально разработанные для многопоточного доступа. Однако вы заметите, что нет ConcurrentList<T>
который работает точно так же, как List. Это связано с тем, что создание поточно-безопасного списка со всеми свойствами списка, таких как произвольный доступ, вставка и удаление и хорошая производительность, практически невозможны. Ближайшим эквивалентом в вашем случае будет System.Collections.Concurrent.ConcurrentQueue <T> или ConcurrentStack <T>.
Однако в вашем случае может быть более простой способ:
Доступ к списку только для чтения всегда является потокобезопасным. Вы можете перебирать свой список или получать доступ к случайным элементам из количества потоков, сколько хотите, при условии, что вы не измените список.
Добавление элементов в список не является потокобезопасным. Это будет очевидно, если вы перейдете по списку при добавлении элементов, вы получите исключение: "Коллекция была изменена после того, как счетчик был создан".
Но даже добавление элементов из нескольких потоков без повторения списка в одно и то же время небезопасно. Вы не получите такой очевидной ошибки, вместо этого она будет работать иногда, а иногда и нет.
Если вы добавляете элементы только один раз после запуска программы, вы можете получить обычный список. Просто убедитесь, что никакие потоки чтения не запущены, пока вы добавляете элементы в список в одном потоке записи. После того, как вы добавили все элементы в список, вы можете перебирать его из столько потоков, сколько хотите.
Для более сложных сценариев обычно лучше переключиться на ConcurrentQueue или ConcurrentStack, вместо того, чтобы внедрять собственные поточно-безопасные методы с использованием lock
.
Ответ №.
Обычные коллекции не являются потокобезопасными.
Вы должны использовать поточно-безопасные аналоги коллекций *. Узнайте больше об этих коллекциях в MSDN.
lock
, поточно-ориентированная коллекция не сможет вам помочь.