Использование ключевого слова C# Volatile в многопоточном приложении
У меня есть класс, в котором есть несколько arraylists.
Мой основной класс создает новый экземпляр этого класса. В моем основном классе есть как минимум 2 потока, добавляющие и удаляющие из моего класса с массивами в нем. На данный момент все работает нормально, но мне просто интересно, будет ли безопаснее объявить мой класс с массивами в нем как volatile например /
private volatile myclass;
myclass = new myclass();
......
myclass.Add(...)
myclass.Clear(..)
2 ответа
Использование ключевого слова volatile не сделает ваш код потокобезопасным в этом примере. Ключевое слово volatile обычно используется для того, чтобы при чтении или записи значения переменной (т. Е. Поля класса) последнее значение для этой переменной либо считывалось из основной памяти, либо записывалось прямо в основную память, а не читалось из кеша (например, регистр процессора) например. Ключевое слово volatile - это способ сказать "не использовать оптимизацию кэширования с этим общим полем", и устраняет проблему, когда потоки могут использовать локальные копии поля и не видеть обновления друг друга.
В вашем случае значение myclass на самом деле не обновляется (то есть вы не переопределяете myclass), поэтому volatile бесполезно для вас, и это не обновление переменной myclass, которое вы действительно хотите сделать поточно-безопасным в этом случае. дело в любом случае.
Если вы хотите сделать обновление фактического класса поточно-безопасным, тогда использование "блокировки" вокруг "Добавить" и "Очистить" является прямой альтернативой. Это гарантирует, что только один поток одновременно может выполнять эти операции (которые обновляют внутреннее состояние myclass), и поэтому не должен выполняться параллельно.
Блокировка может быть использована следующим образом:
private readonly object syncObj = new object();
private readonly myclass = new myclass();
......
lock (syncObj)
{
myclass.Add(...)
}
lock (syncObj)
{
myclass.Clear(..)
}
Вам также необходимо добавить блокировку вокруг любого кода, который считывает состояние, которое обновляется с помощью "Добавить", если это так, хотя это не отображается в вашем примере кода.
При первом написании многопоточного кода может быть неочевидно, зачем вам нужна блокировка при добавлении в коллекцию. Если мы возьмем List или ArrayList в качестве примера, то проблема возникает из-за того, что внутренне эти коллекции используют Array в качестве резервного хранилища и будут динамически "наращивать" этот Array (т. Е. Создавая новый больший массив и копируя старое содержимое), как определенно мощности встречаются при вызове Add. Все это происходит внутри и требует обслуживания этого массива и переменных, таких как текущий размер коллекции (а не длина фактического массива, который может быть больше). Таким образом, добавление в коллекцию может включать несколько шагов, если внутренний массив должен расти. При использовании нескольких потоков небезопасным образом, несколько потоков могут косвенно вызывать рост при добавлении и, таким образом, растоптывать все обновления друг друга. Помимо проблемы одновременного добавления нескольких потоков, существует также проблема, связанная с тем, что другой поток может пытаться прочитать коллекцию во время изменения внутреннего состояния. Использование блокировок гарантирует, что подобные операции выполняются без вмешательства других потоков.
В настоящее время код неверен; добавив volatile
Ключевое слово не исправит это. Использование классов.NET в разных потоках небезопасно без добавления синхронизации.
Трудно дать простой совет, не зная больше о структуре вашего кода. Первым шагом было бы начать использовать lock
ключевое слово вокруг всех обращений к объекту списка; однако в коде все еще могут быть предположения, которые не работают в нескольких потоках.
Можно использовать класс коллекции, который уже безопасен для многопоточного доступа, что позволит избежать необходимости получения lock
Ключевое слово в нужном месте, но все же возможно сделать ошибки.
Можете ли вы опубликовать еще немного своего кода? Таким образом, мы можем дать более конкретные предложения по обеспечению безопасности потока.