Страница 404 из 502
<b> sum);</b>
<b> Thread.Sleep(10); // разрешить переключение задач</b>
<b> }</b>
<b> return sum;</b>
<b> }</b>
<b> }</b>
<b>}</b>
<b>class MyThread {</b>
<b> public Thread Thrd;</b>
<b> int[] a;</b>
<b> int answer;</b>
<b> // Создать один объект типа SumArray для всех</b>
<b> // экземпляров класса MyThread.</b>
<b> static SumArray sa = new SumArray();</b>
<b> // Сконструировать новый поток,</b>
<b> public MyThread(string name, int [ ] nums) {</b>
<b> a = nums;</b>
<b> Thrd = new Thread(this.Run);</b>
<b> Thrd.Name = name;</b>
<b> Thrd.Start(); // начать поток</b>
<b> }</b>
<b> // Начать выполнение нового потока,</b>
<b> void Run() {</b>
<b> Console.WriteLine(Thrd.Name + " начат.");</b>
<b> answer = sa.SumIt(a);</b>
<b> Console.WriteLine("Сумма для потока " + Thrd.Name +</b>
<b> " равна " + answer);</b>
<b> Console.WriteLine(Thrd.Name + " завершен.");</b>
<b> }</b>
<b>}</b>
<b>class Sync {</b>
<b> static void Main() {</b>
<b> int[] a = {1, 2, 3, 4, 5};</b>
<b> MyThread mt1 = new MyThread ("Потомок #1", a);</b>
<b> MyThread mt2 = new MyThread("Потомок #2", a);</b>
<b> mt1.Thrd.Join();</b>
<b> mt2.Thrd.Join() ;</b>
<b> }</b>
<b>}</b>
Ниже приведен результат выполнения данной программы, хотя у вас он может оказаться несколько иным.
<b>Потомок #1 начат.</b>
<b>Потомок #2 начат.</b>
<b>Текущая сумма для потока Потомок #1 равна 1</b>
<b>Текущая сумма для потока Потомок #1 равна 3</b>
<b>Текущая сумма для потока Потомок #1 равна 6</b>
<b>Текущая сумма для потока Потомок #1 равна 10</b>
<b>Текущая сумма для потока Потомок #1 равна 15</b>
<b>Сумма для потока Потомок #1 равна 15</b>
<b>Потомок #1 завершен.</b>
<b>Текущая сумма для потока Потомок #2 равна 1</b>
<b>Текущая сумма для потока Потомок #2 равна 3</b>
<b>Текущая сумма для потока Потомок #2 равна 6</b>
<b>Текущая сумма для потока Потомок #2 равна 10</b>
<b>Текущая сумма для потока Потомок #2 равна 15</b>
<b>Сумма для потока Потомок #2 равна 15</b>
<b>Потомок #2 завершен.</b>
Как следует из приведенного выше результата, в обоих потоках правильно подсчитывается сумма, равная 15.
Рассмотрим эту программу более подробно. Сначала в ней создаются три класса. Первым из них оказывается класс SumArray, в котором определяется метод SumIt(), суммирующий элементы целочисленного массива. Вторым создается класс MyThread, в котором используется статический объект sa типа SumArray. Следовательно, единственный объект типа SumArray используется всеми объектами типа MyThread. С помощью этого объекта получается сумма элементов целочисленного массива. Обратите внимание на то, что текущая сумма запоминается в поле sum объекта типа SumArray. Поэтому если метод SumIt() используется параллельно в двух потоках, то оба потока попытаются обратиться к полю sum, чтобы сохранить в нем текущую сумму. А поскольку это может привести к ошибкам, то доступ к методу SumIt() должен быть синхронизирован. И наконец, в третьем классе, Sync, создаются два потока, в которых подсчитывается сумма элементов целочисленного массива.
Оператор lock в методе SumIt() препятствует одновременному использованию данного метода в разных потоках. Обратите внимание на то, что в операторе lock объект lockOn используется в качестве синхронизируемого. Это закрытый объект, предназначенный исключительно для синхронизации. Метод Sleep() намеренно вызывается для того, чтобы произошло переключение задач, хотя в данном случае это невозможно. Код в методе SumIt() заблокирован, и поэтому он может быть одновременно использован только в одном потоке. Таким образом, когда начинает выполняться второй порожденный поток, он не сможет войти в метод SumIt() до тех пор, пока из него не выйдет первый порожденный поток. Благодаря этому гарантируется получение правильного результата.