Проблема конкурентного доступа

Проблема конкурентного доступа

До сих пор все многопоточные приложения, созданные вами при изучении материала этой главы, были устойчивыми в отношении потоков, поскольку в них соответствующие методы вызывались только одним объектом Thread. Конечно, некоторые из ваших приложений могут быть настолько же простыми, но большинство многопоточных приложений содержит очень много вторичных потоков. С учетом того, что все потоки в домене приложения могут претендовать на доступ к открытым данным приложения одновременно, представьте себе, что может случиться, если к одному и тому же элементу данных получит доступ множество потоков. Поскольку планировщик потоков может приостановить работу потока в любой момент времени, что будет, если поток А будет отстранен от выполнения своей работы на полпути до того, как он эту работу завершит? Поток В будет читать некорректные данные.

Чтобы проиллюстрировать проблему конкурентного доступа, давайте построим еще одно консольное приложение C#, которое мы назовем MultiThreadedPrinting, Это приложение будет использовать класс Printer, созданный нами ранее, но на этот раз метод PrintNumbers() "заставит" текущий поток делать паузы произвольной длительности в соответствии со случайно генерируемыми значениями.

public class Printer {

 public void PrintNumbers() {

  …

  for (int i = 0; i ‹ 10; i++) {

   Random r = new Random();

   Thread.Sleep(1000 * r.Next(5));

   Console.Write(i + ", ");

  }

  Console.WriteLine();

 }

}

Метод Main() отвечает за создание массива из десяти объектов Thread с уникальными именами), каждый из который вызывает один и тот же экземпляр Printer.

class Program {

 static void Main(string[] args) {

  Console.WriteLine("***** Синхронизация потоков ***** ");

  Printer p = new Printer();

  // Создание 10 потоков, указывающих на один и тот же метод

  // одного и того же объекта.

 Thread[] threads = new Thread[10];

  for (int i = 0; i ‹ 10; i++) {

   threads[i] =new Thread(new ThreadStart(p.PrintNumbers));

   threads[i].Name = string.Format("Рабочий поток #{0}", i);

  }

  // Теперь старт каждого их них.

  foreach (Thread t in threads) t.Start();

  Console.ReadLine();

 }

}

Перед тем как выполнить тестовый запуск программы, давайте обсудим cо-ответствующую проблему. Здесь первичный поток в рамках домена приложения порождает десять вторичных рабочих потоков. Каждому рабочему потоку дается указание вызвать метод PrintNumbers() одного и того же экземпляра Printer. Поскольку здесь не предпринято никаких мер по блокированию общедоступных ресурсов данного объекта (консоли), имеется большая вероятность того, что текущий поток будет приостановлен до того, как метод PrintNumbers() закончит вывод всех своих результатов. Вы не знаете точно, когда это случиться (и случится ли вообще), поэтому нужно быть готовым к непредвиденным результатам. Например, может получиться вывод, показанный на рис. 14.8.

Рис. 14.8. Конкуренция в действии, первая попытка

Выполните приложение еще несколько раз. На рис. 14.9 показана другая возможность вывода (ваши результаты, очевидно, тоже будут другими).

Рис. 14.9. Конкуренция в действии, вторая попытка

Ясно, что проблемы здесь действительно есть. Каждый поток дает указание объекту Printer печатать числовые данные, и планировщик потоков запускает выполнение этих потоков в фоновом режиме. В результате получается несогласованный вывод. В этом случае мы должны программно организовать синхронизованный доступ к совместно используемым ресурсам. Нетрудно догадаться, что в пространстве имен System.Threading есть целый ряд типов, имеющих отношение к синхронизации. А язык программирования C# предлагает специальное ключевое слово, как раз для решения задач синхронизации совместного доступа к данным в многопоточных приложениях.

Замечание. Если у вас не получается сгенерировать непредвиденный вывод, увеличьте число потоков с 10 до 100 (например) или добавьте в свою программу вызов Thread.Sleep(). В конце концов вы все равно столкнетесь с проблемой конкурентного доступа

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Часть 1. Проблема

Из книги Экстремальное программирование автора Бек Кент

Часть 1. Проблема В данной части книги подготавливается сцена, на которой должно в последующем появиться экстремальное программирование. Здесь описываются различные аспекты проблемы, которую предстоит решить, сформировав новую дисциплину разработки программного


Проблема выбора

Из книги Журнал `Компьютерра` N733 автора Журнал «Компьютерра»

Проблема выбора Автор: Олег ВолошинПохоже, что развитие цифровых камер достигло некоторого промежуточного потолка. Нет, разумеется, в техническом плане есть масса перспективных направлений.Тем не менее отличие новой камеры, выпущенной "на днях", от аналогичной, но


Проблема

Из книги Давайте создадим компилятор! автора Креншоу Джек


В чём ваша проблема?

Из книги Getting Real (на русском) [вычитывается] автора 37signals

В чём ваша проблема? Разрабатывайте ПО для себяПри создании программ большую часть времени будет занимать решение ваших собственных проблем. Вы и будете тем самым потенциальным клиентом, соответственно и знание о необходимом у вас уже есть. Это даёт вам отличное начало


Проблема тогда, когда это проблема

Из книги Компьютерра #27-28 (791-792) автора Автор неизвестен

Проблема тогда, когда это проблема Не тратьте бесцельно время на проблемы, которых у вас еще нетВам действительно нужно волноваться о вычислениях для 100 000 потребителей сегодня, если это будет у вас через два года?Действительно вам нужно нанять восемь программистов, если


ПРОБЛЕМА ЛЕБЕДЯ

Из книги Примеры использования Паттерн Singleton (Одиночка) автора Федоров Дмитрий


Проблема наследования

Из книги Вариации на тему STL. Адаптер обобщенного указателя на функцию-член класса автора Гусаров Михаил

Проблема наследования Если существует необходимость наследовать от класса Singleton, то следует придерживаться определенных правил.Во-первых, класс-наследник должен переопределить метод Instance(), так, чтобы создавать экземпляр производного класса. Если не предполагается, что


Но в чем тогда проблема?

Из книги Язык программирования С# 2005 и платформа .NET 2.0. [3-е издание] автора Троелсен Эндрю

Но в чем тогда проблема? Обобщенный указатель всего лишь «прикидывается» указателем и не может быть использован везде, где используются обычные указатели. Например, возьмем адаптер указателя на функцию-член класса из STL:template<class R, class T> mem_fun_t<R, T> mem_fun(R (T::*pm)());


Проблема состояния

Из книги Основы объектно-ориентированного программирования автора Мейер Бертран

Проблема состояния В начале предыдущей главы было указано, что HTTP является сетевым протоколом, не обеспечивающим сохранение состояний. Именно этот факт делает процесс разработки Web-приложений столь отличающимся от процесса построения выполняемого компоновочного


Техническая проблема

Из книги Инфобизнес на полную мощность [Удвоение продаж] автора Парабеллум Андрей Алексеевич

Техническая проблема Как же должен выглядеть повторно используемый модуль?


Проблема надежности

Из книги Язык Си - руководство для начинающих автора Прата Стивен

Проблема надежности Допустим, разработчик управляет утилизацией объектов с помощью механизма reclaim. Возможность ошибочного вызова reclaim всегда существует; особенно при наличии сложных структур данных. В жизненном цикле ПО reclaim, бывшее когда-то правильным, может стать


Проблема

Из книги автора

Проблема Рассмотрим пример стека, но уже не как АТД, а как класс. Мы знаем, как написать класс INTEGER_STACK, задающий стек объектов типа INTEGER. Компоненты будут включать count (число элементов), put (вталкивание элемента), item (элемент в вершине), remove (выталкивание элемента), empty (пустой ли


Проблема

Из книги автора

Проблема Из этих примеров ясно: нам может понадобиться механизм удостоверения типа объекта.Решение этой проблемы, возникающей в специфических, но критически важных случаях, должно быть найдено без потери преимуществ ОО-стиля разработки. В частности, мы не хотим


Проблема типизации

Из книги автора

Проблема типизации Эффективное применение объектной технологии требует четкого описания в тексте системы типов всех объектов, с которыми она работает на этапе выполнения. Это правило, известное как статическая типизация (static typing), делает наше ПО:[x]. более надежным,


ПРОБЛЕМА ВВОДА

Из книги автора

ПРОБЛЕМА ВВОДА      Существует несколько способов последовательного ввода набора данных, скажем чисел. Мы обсудим здесь некоторые из них, переходя от менее удобных к более удобным.      Вообще говоря, наименее удобный способ - это тот, который мы только что использовали;