Является ли ссылочное назначение потоковым?
Я создаю многопоточный кеш в С#, который будет содержать список объектов Car:
public static IList<Car> Cars {get; private set;}
Мне интересно, можно ли изменить ссылку в потоке без блокировки?
например.
private static void Loop()
{
while (true)
{
Cars = GetFreshListFromServer();
Thread.Sleep(SomeInterval);
}
}
В основном это сводится к тому, что присвоение новой ссылки на "Автомобили" является атомной или нет, я бы предположил.
Если это не так, мне, очевидно, придется использовать личное поле для моих автомобилей и блокировать получение и настройки.
Ответы
Ответ 1
Да, обновления ссылок гарантированно будут атомарными в спецификации языка.
5.5 Атоматичность переменных ссылок
Считывание и запись следующих типов данных: atomic: bool, char, byte, sbyte, short, ushort, uint, int, float и reference. Кроме того, чтение и запись типов перечислений с базовым типом в предыдущем списке также являются атомарными. Чтения и записи других типов, включая длинные, улоновые, двойные и десятичные, а также определяемые пользователем типы, не гарантируются как атомарные.
Однако внутри жесткой петли вы можете укусить кеширование регистра. Вряд ли в этом случае, если ваш метод-вызов не вставлен (что может случиться). Лично я бы добавил lock
, чтобы сделать его простым и предсказуемым, но volatile
тоже может помочь. И обратите внимание, что полная безопасность потока - это больше, чем просто атомарность.
В случае кеша я бы посмотрел на Interlocked.CompareExchange
, лично - то есть попытаюсь обновить, но если он не выполнит повторную работу с нуля (начиная с нового значения) и повторите попытку.
Ответ 2
В ответе @Marc Gravell, как указано в С# Language Spec 5.5, важно знать, что подразумевается под термином "определяемый пользователем тип". Я не нашел четкого определения w.r.t. это использование в языке С# Spec. В UML и в общем выражении класс является экземпляром типа. Но в контексте С# Language Spec это значение неясно.
Раздел ссылок на Visual Basic "Определенные пользователем типы" (в https://msdn.microsoft.com/en-us/library/cec05s9z.aspx) говорит
"Предыдущие версии Visual Basic поддерживают пользовательский тип (UDT). Текущая версия расширяет UDT до структуры.
поэтому кажется, что пользовательский тип является структурой, а не классом.
Но....
В соответствии с "Руководством по программированию на С#" "Типы" (в https://msdn.microsoft.com/en-us/library/ms173104.aspx):
"Типичная программа С# использует типы из библиотеки классов, а также определяемые пользователем типы"
который подразумевает, что класс является определяемым пользователем типом. Позже он приводит пример "сложных пользовательских типов:"
MyClass myClass;
что означает, что "MyClass" является определяемым пользователем типом. И позже он говорит:
"Каждый тип в CTS определяется как тип значения или ссылка тип. Сюда входят все пользовательские типы в классе .NET Framework библиотеки, а также ваши собственные пользовательские типы."
... что подразумевает, что все классы, созданные разработчиком, являются "Пользовательским типом".
И, наконец, есть этот элемент Stackoverflow, в котором значение этого термина обсуждается бесконечно: Как определить, является ли свойство определяемым пользователем типом в С#?
Поэтому, чтобы быть в безопасности, я вынужден рассматривать все Классы, созданные мной или те, которые содержатся в .Net Framework, все должны быть определенными пользователем типами, и поэтому Not Thread Safe для назначения, потому что он говорит в разделе 5.5 языка С#:
Считывание и запись... а также пользовательских типов не гарантируется атомарным.
К сожалению, разговорный термин используется в точной спецификации, такой как С# Language Specification. Из-за этой двусмысленности, чтобы быть потокобезопасным, я могу писать менее оптимальный код, чем это было бы возможно, если окажется, что "Пользовательский тип" не включает классы CLR.
Поэтому я прошу дать дополнительное разъяснение этому ответу stackoverflow, поскольку его текущая основа для ответа оставляет эту значительную двусмысленность. Как бы то ни было, ответ на вопрос " Является ли ссылочным назначением потокобезопасным?" кажется " НЕТ".