Console.WriteLine(Thrd.Name + ' завершен.');
}
}
class Sync {
static void Main() {
int[] a = {1, 2, 3, 4, 5};
MyThread mtl = new MyThread('Потомок #1', a);
MyThread mt2 = new MyThread('Потомок #2', a);
mtl.Thrd.Join(); mt2.Thrd.Join();
В данной программе блокируется вызов метода sa . Sum It (), а не сам метод Sum It () . Ниже приведена соответствующая строка кода, в которой осуществляется подобная блокировка.
// Заблокировать вызовы метода Sumlt() . lock(sa) answer = sa.Sumlt(a);
Объект sa является закрытым, и поэтому он может быть благополучно заблокирован. При таком подходе к синхронизации потоков данная программа дает такой же правильный результат, как и при первоначальном подходе.
Класс Monitor и блокировка
Ключевое слово lock на самом деле служит в C# быстрым способом доступа к средствам синхронизации, определенным в классе Monitor, который находится в пространстве имен System. Threading. В этом классе определен, в частности, ряд методов для управления синхронизацией. Например, для получения блокировки объекта вызывается метод Enter (), а для снятия блокировки — метод Exit (). Ниже приведены общие формы этих методов:
public static void Enter(object
где
Впрочем, один метод из класса Monitor может все же оказаться полезным. Это метод TryEnter (), одна из общих форм которого приведена ниже.
public static bool TryEnter(object
Этот метод возвращает логическое значение true, если вызывающий поток получает блокировку для объекта
Кроме того, в классе Monitor определены методы Wait (), Pulse () и PulseAll (), которые рассматриваются в следующем разделе.
Сообщение между потоками с помощью методов Wait (), Pulse () и PulseAll ()
Рассмотрим следующую ситуацию. Поток Г выполняется в кодовом блоке lock, и ему требуется доступ к ресурсу
среды. Более совершенное решение заключается в том, чтобы временно освободить объект и тем самым дать возможность выполняться другим потокам. Такой подход основывается на некоторой форме сообщения между потоками, благодаря которому один поток может уведомлять другой о том, что он заблокирован и что другой поток может возобновить свое выполнение. Сообщение между потоками организуется в C# с помощью методов Wait (), Pulse () и PulseAll ().
Методы Wait (), Pulse () и PulseAll () определены в классе Monitor и могут вызываться только из заблокированного фрагмента блока. Они применяются следующим образом. Когда выполнение потока временно заблокировано, он вызывает метод Wait (). В итоге поток переходит в состояние ожидания, а блокировка с соответствующего объекта снимается, что дает возможность использовать этот объект в другом потоке. В дальнейшем ожидающий поток активизируется, когда другой поток войдет в аналогичное состояние блокировки, и вызывает метод Pulse () или PulseAll (). При вызове метода Pulse () возобновляется выполнение первого потока, ожидающего своей очереди на получение блокировки. А вызов метода PulseAll () сигнализирует о снятии блокировки всем ожидающим потокам.
Ниже приведены две наиболее часто используемые формы метода Wait ().
