Подтвердить что ты не робот

Почему List <T> не потокобезопасен?

Со следующего сайта:

http://crfdesign.net/programming/top-10-differences-between-java-and-c

К сожалению, List<> не является потокобезопасным (С# s ArrayList и Javas Vector являются потокобезопасными). С# также имеет Hashtable; общая версия:

Что делает List<T> не потокобезопасным? Это проблема с реализацией части .NET Framework? Или генерики не являются потокобезопасными?

4b9b3361

Ответ 1

Вам действительно нужно классифицировать Java-тип безопасности потоков. Javas Vector безопасен для использования из нескольких потоков, поскольку использует методы синхронизации. Государство не будет повреждено.

Однако полезность вектора Java ограничена несколькими потоками без дополнительной синхронизации. Например, рассмотрим простой акт чтения элемента из вектора

Vector vector = getVector();
if ( vector.size() > 0 ) { 
  object first = vector.get(0);
}

Этот метод не испортит состояние вектора, но он также неверен. Ничто не останавливает другой поток от мутации вектора между оператором if и вызовом get(). Этот код может и будет в конечном итоге сбой из-за состояния гонки.

Этот тип синхронизации полезен только в нескольких сценариях, и это, безусловно, не дешево. Вы платите заметную цену за синхронизацию, даже если вы не используете несколько потоков.

.Net решила не платить эту цену по умолчанию за сценарий ограниченной ограниченности. Вместо этого он решил реализовать свободный от блокировки список. Авторы несут ответственность за добавление любой синхронизации. Это ближе к модели С++ "платите только за то, что вы используете"

Недавно я написал несколько статей об опасностях использования коллекций с внутренней синхронизацией, такой как вектор Java.

Ссылка на векторную безопасность потока: http://www.ibm.com/developerworks/java/library/j-jtp09263.html

Ответ 2

Почему это было бы поточно-безопасным? Не каждый класс. Фактически, по умолчанию классы не являются потокобезопасными.

Будучи потокобезопасным, будет означать, что любая операция, изменяющая список, должна быть блокирована от одновременного доступа. Это было бы необходимо даже для тех списков, которые будут использоваться только одним потоком. Это было бы очень неэффективно.

Ответ 3

Это просто дизайнерское решение для реализации типов, не зависящих от потоков. Коллекции предоставляют свойство SyncRoot интерфейса ICollection и метода Synchronized() для некоторых коллекций для явной синхронизации типов данных.

Используйте SyncRoot для блокировки объекта в многопоточных средах.

lock (collection.SyncRoot)
{
   DoSomething(collection);
}

Используйте collection.Synchronized(), чтобы получить потокобезопасную оболочку для коллекции.

Ответ 4

Для обеспечения правильной безопасности потоков List<> и другие типы коллекций должны быть неизменными. С параллельными расширениями .NET, выходящими в .NET 4.0, мы увидим потокобезопасные версии наиболее часто используемых коллекций. Jon Skeet затрагивает некоторые из этих.

Ответ 5

Вероятность использования гонки JaredPar - это страшное следствие того, что он полагается на векторную безопасность потока. Это то, что приводит к тому, что "каждый девятый вторник приложение делает что-то странное" - отрывок отчета о дефектах, который сведёт вас с ума.

Существует ряд действительно потокобезопасных коллекций входящих в .Net 4, с интересным побочным эффектом, threaded модификация коллекции при перечислении, но там производительность, который поставляется с потоковой безопасностью, иногда довольно большой.

Таким образом, логическая задача для разработчика инфраструктуры - сохранить максимально возможный класс для 95% пользователей, которые, вероятно, не будут обрабатывать потоки, и полагаются на тех, кто делает многопоточность, чтобы знать, что у них есть сделать это безопасно.

Ответ 6

использовать SynchronizedCollection, он также предоставляет конструктор-параметр для использования общей синхронизации:)