Добавить в цитаты Настройки чтения

Страница 410 из 502

<b>    Console.Write(&quot;тик &quot;);</b>

<b>    Monitor.Pulse(this); // разрешить выполнение метода Tock()</b>

<b>    Monitor.Wait(this);    //    ожидать завершения метода Tock()</b>

<b>  }</b>

<b>  /* Следующий атрибут полностью синхронизирует метод Тоск(). */</b>

<b>  [MethodImplAttribute(MethodImplOptions.Synchronized)]</b>

<b>  public void Tock(bool ru

<b>    if (!ru

<b>      Monitor.Pulse(this); // уведомить любые ожидающие потоки</b>

<b>      return;</b>

<b>    }</b>

<b>    Console.WriteLine(&quot;так&quot;);</b>

<b>    Monitor.Pulse(this); // разрешить выполнение метода Tick()</b>

<b>    Monitor.Wait(this);    //    ожидать завершения метода Tick()</b>

<b>  }</b>

<b>}</b>

<b>class MyThread {</b>

<b>  public Thread Thrd;</b>

<b>  TickTock ttOb;</b>

<b>  // Сконструировать новый поток.</b>

<b>  public MyThread(string name, TickTock tt) {</b>

<b>    Thrd = new Thread(this.Run);</b>

<b>    ttOb = tt;</b>

<b>    Thrd.Name = name;</b>

<b>    Thrd.Start();</b>

<b>  }</b>

<b>  // Начать выполнение нового потока,</b>

<b>  void Run() {</b>

<b>    if (Thrd.Name == &quot;Tick&quot;) {</b>

<b>      for (int i = 0; i &lt; 5; i++) ttOb.Tick(true);</b>

<b>      ttOb.Tick(false);</b>

<b>    }</b>

<b>    else {</b>

<b>      for (int i = 0; i &lt; 5; i++) ttOb.Tock(true);</b>

<b>      ttOb.Tock(false);</b>

<b>    }</b>

<b>  }</b>

<b>}</b>

<b>class TickingClock {</b>

<b>  static void Main() {</b>

<b>    TickTock tt = new TickTock();</b>

<b>    MyThread mt1 = new MyThread(&quot;Tick&quot;, tt);</b>

<b>    MyThread mt2 = new MyThread(&quot;Tock&quot;, tt);</b>

<b>    mt1.Thrd.Join();</b>

<b>    mt2.Thrd.Join();</b>

<b>    Console.WriteLine(&quot;Часы остановлены&quot;);</b>

<b>  }</b>

<b>}</b>

Эта версия программы дает такой же результат, как и предыдущая. Синхронизируемый метод не определен в открытом классе и не вызывается для открытого объекта, поэтому применение оператора lock или атрибута MethodlmplAttribute зависит от личных предпочтений. Ведь и тот и другой дает один и тот же результат. Но поскольку ключевое слово lock относится непосредственно к языку С#, то в примерах, приведенных в этой книге, предпочтение отдано именно ему.

----------------------------

ПРИМЕЧАНИЕ

Не применяйте атрибут MethodImplAttribute в открытых классах или экземплярах открытых объектов. Вместо этого пользуйтесь оператором lock, чтобы заблокировать метод для закрытого объекта, как пояснялось ранее.

----------------------------

Применение мьютекса и семафора

В большинстве случаев, когда требуется синхронизация, оказывается достаточно и оператора lock. Тем не менее в некоторых случаях, как, например, при ограничении доступа к общим ресурсам, более удобными оказываются механизмы синхронизации, встроенные в среду .NET Framework. Ниже рассматриваются по порядку два таких механизма: мьютекс и семафор.

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

Мьютекс поддерживается в классе System.Threading.Mutex. У него имеется несколько конструкторов. Ниже приведены два наиболее употребительных конструктора.

<b>public Mutex()</b>

<b>public Mutex(bool initiallyOwned)</b>

В первой форме конструктора создается мьютекс, которым первоначально никто не владеет. А во второй форме исходным состоянием мьютекса завладевает вызывающий поток, если параметр ini tiallyOwned имеет логическое значение true. В противном случае мьютексом никто не владеет.

Для того чтобы получить мьютекс, в коде программы следует вызвать метод WaitOne() для этого мьютекса. Метод WaitOne() наследуется классом Mutex от класса Thread.WaitHandle. Ниже приведена его простейшая форма.