Книга: ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание

Синхронизация с помощью типа System.Threading.Interlocked

Синхронизация с помощью типа System.Threading.Interlocked

В это всегда верится с трудом, пока вы не проверите соответствующий программный код CIL, но и операции присваивания, и базовые арифметические операции не являются атомарными. Поэтому в пространстве имен System.Threading предлагается тип, позволяющий воздействовать на отдельный элемент данных атомарно с меньшей нагрузкой, чем это делает тип Monitor. Тип класса Interlocked определяет статические члены, описания которых приведены в табл. 14.4.

Таблица 14.4. Члены типа System.Threading.Interlocked

Член Описание
CompareExchange() Безопасно проверяет два значения на равенство, и если они равны, заменяет одно из значений третьим
Decrement() Безопасно уменьшает значение на 1
Exchange() Безопасно меняет два значения местами
Increment() Безопасно выполняет приращение значения на 1

Хотя это может и не казаться очевидным на первый взгляд, процесс атомарного изменения одного значения является вполне типичным в многопоточном окружении. Предположим, что у нас есть метод AddOne(), который увеличивает целочисленную переменную intVal на единицу. Вместо программного кода синхронизации, подобного следующему;

public void AddOne() {
 lock(this) {
  intVal++;
 }
}

можно предложить более простой программный код, в котором используется статический метод Interlocked.Increment(). Просто передайте переменную для приращения по ссылке. Обратите внимание на то, что метод Increment() не только изменяет значение поступающего параметра, но и возвращает новое значение.

public void AddOne() {
 int newVal = Interlocked.Increment(ref intVal);
}

В дополнение к Increment() и Decrement() тип Interlocked позволяет атомарно присваивать числовые и объектные данные. Например, если вы хотите присвоить члену-переменной значение 83, вы можете избежать необходимости явного использования оператора lock (или явного применения логики Monitor), если используете метод Interlocked.Exchange().

public void SafeAssignment() {
 Interlocked.Exchange(ref myInt, 83);
}

Наконец, при проверке двух значений на равенство, чтобы обеспечить потоковую безопасность элементу сравнения, можете использовать метод Interlocked.CompareExchange(), как показано ниже.

public void CompareAndExchange() {
 // Если значением i является 83, изменить его на 99.
 Interlocked.CompareExchange(ref i, 99, 83);
}

Оглавление книги


Генерация: 1.174. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз