Использование ключевого слова C # Volatile в многопоточном приложении - PullRequest
2 голосов
/ 28 июля 2010

У меня есть класс, в котором есть несколько массивов.

Мой основной класс создает новый экземпляр этого класса.В моем основном классе есть как минимум 2 потока, добавляющие и удаляющие из моего класса с массивами в нем.На данный момент все работает нормально, но мне просто интересно, будет ли безопаснее объявить мой класс с массивами в нем как volatile, например / / 1003 *

private volatile myclass;
myclass = new myclass();
......
myclass.Add(...)
myclass.Clear(..)

Ответы [ 2 ]

4 голосов
/ 28 июля 2010

Использование ключевого слова volatile не сделает ваш код поточно-ориентированным в этом примере. Ключевое слово volatile обычно используется для того, чтобы при чтении или записи значения переменной (т. Е. Поля класса) последнее значение для этой переменной либо считывалось из основной памяти, либо записывалось прямо в основную память, а не читалось из кеша (например, регистр процессора) например. Ключевое слово volatile - это способ сказать «не использовать оптимизацию кэширования с этим общим полем», и устраняет проблему, когда потоки могут использовать локальные копии поля и не видеть обновления друг друга.

В вашем случае значение myclass на самом деле не обновляется (т.е. вы не переназначаете myclass), так что volatile бесполезно для вас, и это не обновление переменной myclass, которую вы действительно хотите сделать thread- в любом случае безопасно в этом случае.

Если вы хотите сделать обновление реального класса поточно-безопасным, тогда использование «блокировки» вокруг «Добавить» и «Очистить» является прямой альтернативой. Это гарантирует, что только один поток одновременно может выполнять эти операции (которые обновляют внутреннее состояние 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. Все это происходит внутри и требует обслуживания этого массива и переменных, таких как текущий размер коллекции (а не длина фактического массива, который может быть больше). Поэтому добавление в коллекцию может включать несколько шагов, если внутренний массив должен расти. При использовании нескольких потоков небезопасным образом, несколько потоков могут косвенно вызывать рост при добавлении и, таким образом, растоптывать все обновления друг друга. Помимо проблемы одновременного добавления нескольких потоков, существует также проблема, связанная с тем, что другой поток может пытаться прочитать коллекцию , в то время как внутреннее состояние изменяется. Использование блокировок гарантирует, что подобные операции выполняются без вмешательства других потоков.

2 голосов
/ 28 июля 2010

В настоящее время код неверный;добавление ключевого слова volatile не исправит это.Использование классов .NET в потоках без добавления синхронизации небезопасно.

Трудно дать простой совет, не зная больше о структуре вашего кода.Первым шагом было бы начать использовать ключевое слово lock для всех обращений к объекту списка;однако в коде все еще могут быть предположения, которые не работают в нескольких потоках.

Можно использовать класс коллекции, который уже безопасен для многопоточного доступа, что позволит избежать необходимости получения lockключевое слово в нужном месте, но все еще возможно делать ошибки.

Можете ли вы опубликовать еще немного своего кода?Таким образом, мы можем дать более конкретные рекомендации по обеспечению безопасности потока.

...