Kniga-Online.club
» » » » Герберт Шилдт - C# 4.0: полное руководство

Герберт Шилдт - C# 4.0: полное руководство

Читать бесплатно Герберт Шилдт - C# 4.0: полное руководство. Жанр: Программирование издательство -, год 2004. Так же читаем полные версии (весь текст) онлайн без регистрации и SMS на сайте kniga-online.club или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.
Перейти на страницу:

      sum =0; // установить исходное значение суммы

      for(int i=0; i < nums.Length; i++) {

        sum += nums[i];

        Console.WriteLine("Текущая сумма для потока " +

               Thread.CurrentThread.Name + " равна " +

               sum);

        Thread.Sleep(10); // разрешить переключение задач

      }

      return sum;

    }

  }

}

class MyThread {

  public Thread Thrd;

  int[] a;

  int answer;

  // Создать один объект типа SumArray для всех

  // экземпляров класса MyThread.

  static SumArray sa = new SumArray();

  // Сконструировать новый поток,

  public MyThread(string name, int [ ] nums) {

    a = nums;

    Thrd = new Thread(this.Run);

    Thrd.Name = name;

    Thrd.Start(); // начать поток

  }

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

  void Run() {

    Console.WriteLine(Thrd.Name + " начат.");

    answer = sa.SumIt(a);

    Console.WriteLine("Сумма для потока " + Thrd.Name +

            " равна " + answer);

    Console.WriteLine(Thrd.Name + " завершен.");

  }

}

class Sync {

  static void Main() {

    int[] a = {1, 2, 3, 4, 5};

    MyThread mt1 = new MyThread ("Потомок #1", a);

    MyThread mt2 = new MyThread("Потомок #2", a);

    mt1.Thrd.Join();

    mt2.Thrd.Join() ;

  }

}

Ниже приведен результат выполнения данной программы, хотя у вас он может оказаться несколько иным.

Потомок #1 начат.

Потомок #2 начат.

Текущая сумма для потока Потомок #1 равна 1

Текущая сумма для потока Потомок #1 равна 3

Текущая сумма для потока Потомок #1 равна 6

Текущая сумма для потока Потомок #1 равна 10

Текущая сумма для потока Потомок #1 равна 15

Сумма для потока Потомок #1 равна 15

Потомок #1 завершен.

Текущая сумма для потока Потомок #2 равна 1

Текущая сумма для потока Потомок #2 равна 3

Текущая сумма для потока Потомок #2 равна 6

Текущая сумма для потока Потомок #2 равна 10

Текущая сумма для потока Потомок #2 равна 15

Сумма для потока Потомок #2 равна 15

Потомок #2 завершен.

Как следует из приведенного выше результата, в обоих потоках правильно подсчитывается сумма, равная 15.

Рассмотрим эту программу более подробно. Сначала в ней создаются три класса. Первым из них оказывается класс SumArray, в котором определяется метод SumIt(), суммирующий элементы целочисленного массива. Вторым создается класс MyThread, в котором используется статический объект sa типа SumArray. Следовательно, единственный объект типа SumArray используется всеми объектами типа MyThread. С помощью этого объекта получается сумма элементов целочисленного массива. Обратите внимание на то, что текущая сумма запоминается в поле sum объекта типа SumArray. Поэтому если метод SumIt() используется параллельно в двух потоках, то оба потока попытаются обратиться к полю sum, чтобы сохранить в нем текущую сумму. А поскольку это может привести к ошибкам, то доступ к методу SumIt() должен быть синхронизирован. И наконец, в третьем классе, Sync, создаются два потока, в которых подсчитывается сумма элементов целочисленного массива.

Оператор lock в методе SumIt() препятствует одновременному использованию данного метода в разных потоках. Обратите внимание на то, что в операторе lock объект lockOn используется в качестве синхронизируемого. Это закрытый объект, предназначенный исключительно для синхронизации. Метод Sleep() намеренно вызывается для того, чтобы произошло переключение задач, хотя в данном случае это невозможно. Код в методе SumIt() заблокирован, и поэтому он может быть одновременно использован только в одном потоке. Таким образом, когда начинает выполняться второй порожденный поток, он не сможет войти в метод SumIt() до тех пор, пока из него не выйдет первый порожденный поток. Благодаря этому гарантируется получение правильного результата.

Для того чтобы полностью уяснить принцип действия блокировки, попробуйте удалить из рассматриваемой здесь программы тело метода SumIt(). В итоге метод SumIt() перестанет быть синхронизированным, а следовательно, он может параллельно использоваться в любом числе потоков для одного и того же объекта. Поскольку текущая сумма сохраняется в поле sum, она может быть изменена в каждом потоке, вызывающем метод SumIt(). Это означает, что если два потока одновременно вызывают метод SumIt() для одного и того же объекта, то конечный результат получается неверным, поскольку содержимое поля sum отражает смешанный результат суммирования в обоих потоках. В качестве примера ниже приведен результат выполнения рассматриваемой здесь программы после снятия блокировки с метода SumIt().

Потомок #1 начат.

Потомок #2 начат.

Текущая сумма для потока Потомок #1 равна 1

Текущая сумма для потока Потомок #2 равна 1

Текущая сумма для потока Потомок #1 равна 3

Текущая сумма для потока Потомок #2 равна 5

Текущая сумма для потока Потомок #2 равна 11

Текущая сумма для потока Потомок #1 равна 8

Текущая сумма для потока Потомок #1 равна 15

Текущая сумма для потока Потомок #2 равна 19

Текущая сумма для потока Потомок #1 равна 24

Текущая сумма для потока Потомок #2 равна 29

Сумма для потока Потомок #1 равна 29

Потомок #1 завершен.

Сумма для потока Потомок #2 равна 29

Потомок #2 завершен.

Как следует из приведенного выше результата, в обоих порожденных потоках метод SumIt() используется одновременно для одного и того же объекта, а это приводит к искажению значения в поле sum.

Ниже подведены краткие итоги использования блокировки.

•    Если блокировка любого заданного объекта получена в одном потоке, то после блокировки объекта она не может быть получена в другом потоке.

•    Остальным потокам, пытающимся получить блокировку того же самого объекта, придется ждать до тех пор, пока объект не окажется в разблокированном состоянии.

•    Когда поток выходит из заблокированного фрагмента кода, соответствующий объект разблокируется.

Другой подход к синхронизации потоков

Несмотря на всю простоту и эффективность блокировки кода метода, как показано в приведенном выше примере, такое средство синхронизации оказывается пригодным далеко не всегда. Допустим, что требуется синхронизировать доступ к методу класса, который был создан кем-то другим и сам не синхронизирован. Подобная ситуация вполне возможна при использовании чужого класса, исходный код которого недоступен. В этом случае оператор lock нельзя ввести в соответствующий метод чужого класса. Как же тогда синхронизировать объект такого класса? К счастью, этот вопрос разрешается довольно просто: доступ к объекту может быть заблокирован из внешнего кода по отношению к данному объекту, для чего достаточно указать этот объект в операторе lock. В качестве примера ниже приведен другой вариант реализации предыдущей программы. Обратите внимание на то, что код в методе SumIt() уже не является заблокированным, а объект lockOn больше не объявляется. Вместо этого вызовы метода SumIt() блокируются в классе MyThread.

// Другой способ блокировки для синхронизации доступа к объекту,

using System;

using System.Threading;

class SumArray {

  int sum;

Перейти на страницу:

Герберт Шилдт читать все книги автора по порядку

Герберт Шилдт - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки kniga-online.club.


C# 4.0: полное руководство отзывы

Отзывы читателей о книге C# 4.0: полное руководство, автор: Герберт Шилдт. Читайте комментарии и мнения людей о произведении.


Уважаемые читатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.

  • 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
  • 2. Просьба отказаться от оскорблений, угроз и запугиваний.
  • 3. Просьба отказаться от нецензурной лексики.
  • 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.

Надеемся на Ваше понимание и благоразумие. С уважением, администратор kniga-online.


Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*