Вопрос по Курсу: "Параллельное программирование с использованием MS VisualStudia 2010". При компиляции Самостоятельного задания (одновременная отрисовка прямоугольников, эллипсов и выдача в текст-бокс случайного числа) среда предупреждает: suspend - устаревшая команда; примените monitor, mutex и т.п. Создаётся впечатление, что Задание создано в более поздней среде, чем VS 2010. |
Синхронизация потоков
Классы синхронизации в .NET Framework
Interlocked
Класс Interlocked предоставляет атомарные операции для переменных, общедоступных нескольким потокам. К примеру, операции инкремента (i++) и декремента (i--) которые не являются безопасными при многопоточной обработке. Такие операции могут прерываться планировщиком потоков. Класс Interlocked позволяет выполнять операции инкремента, декремента, обмена и считывания значений, в безопасной к потокам манере.
Применение класса Interlocked является гораздо более быстрым подходом по сравнению с остальными приемами по обеспечению синхронизации. Однако пользоваться им можно для устранения только простых последствий синхронизации.
Имя | Описание |
---|---|
CompareExchange() | Безопасно проверяет два значения на эквивалентность. Если они эквивалентны, изменяет одно из значений на третье |
Decrement() | Безопасно уменьшает значение на 1 |
Exchange() | Безопасно меняет два значения местами |
Increment() | Безопасно увеличивает значение на 1 |
Можно так же использовать оператор lock для блокирования доступа к переменной при установке для нее нового значения, взамен метода Increment():
lock(x) { x++; }
Но можно воспользоваться классом Interlocked. Метод Increment() не только изменяет значение входного параметра, но также возвращает полученное новое значение:
public void Proc() { int x = Interlocked.Increment(ref intVal); }
В дополнение, методы Increment() и Decrement() позволяют автоматически присваивать значения переменным. В примере переменной x присваивается значение 2:
public int x; public void Proc () { Interlocked.Exchange(ref x, 2); }
Класс Monitor
Класс Monitor предназначен для того, чтобы контролировать доступ к объектам, предоставляя блокировку объекта одному потоку. Блокировки объектов предоставляют возможность ограничения доступа к части кода, обычно называемой критической секцией. Пока поток владеет блокировкой для объекта, никакой другой поток не может ею завладеть.
В классе Monitor определено несколько методов синхронизации. Например, чтобы получить возможность блокировки для некоторого объекта, вызывается метод Enter(), а чтобы снять блокировку - метод Exit(). Эти методы имеют следующий формат:
public static void Enter(object syncOb) public static void Exit(object syncOb)
где syncOb - синхронизируемый объект. Если при вызове метода Enter() заданный объект недоступен, вызывающий поток будет ожидать до тех пор, пока объект не станет доступным.
Использование оператора lock эквивалентно вызову метода Enter() с последующим вызовом метода Exit() класса Monitor. Класс Monitor обладает одним важным преимуществом по сравнению с оператором lock: он позволяет добавлять значение тайм-аута для ожидания получения блокировки. Таким образом, вместо того, чтобы ожидать блокировку до бесконечности, можно вызвать метод TryEnter() и передать в нем значение тайм-аута, указывающее, сколько максимум времени должно ожидаться получение блокировки. Один из форматов его использования метода TryEnter():
public static bool TryEnter(object syncOb)
Метод возвращает значение true, если вызывающий поток получает блокировку для объекта syncOb, и значение false в противном случае. Если заданный объект недоступен, вызывающий поток будет ожидать до тех пор, пока он не станет доступным.