Иллюстрированный самоучитель по Visual Basic .NET

Совместная работа с данными по мере их создания

В многопоточных приложениях часто встречается ситуация, когда потоки не только работают с общими данными, но и ожидают их появления (то есть поток 1 должен создать данные, прежде чем поток 2 сможет их использовать). Поскольку данные являются общими, доступ к ним необходимо синхронизировать. Также необходимо предусмотреть средства для оповещения ожидающих потоков о появлении готовых данных.

Подобная ситуация обычно называется проблемой "поставщик/потребитель". Поток пытается обратиться к данным, которых еще нет, поэтому он должен передать управление другому потоку, создающему нужные данные. Проблема решается кодом следующего вида:

  • Поток 1 (потребитель) активизируется, входите синхронизированный метод, ищет данные, не находит их и переходит в состояние ожидания. Предварительно он должен снять блокировку, чтобы не мешать работе потока- поставщика.
  • Поток 2 (поставщик) входит в синхронизированный метод, освобожденный потоком 1, создает данные для потока 1 и каким-то образом оповещает поток 1 о наличии данных. Затем он снимает блокировку, чтобы поток 1 смог обработать новые данные.

Примечание
Не пытайтесь решить эту проблему постоянной активизацией потока 1 с проверкой состояния условной переменной, значение которой устанавливается потоком 2. Такое решение серьезно повлияет на быстродействие вашей программы, поскольку в большинстве случаев поток 1 будет активизироваться без всяких причин; а поток 2 будет переходить в ожидание так часто, что у него не останется времени на создание данных
.

Связи "поставщик/потребитель" встречаются очень часто, поэтому в библиотеках классов многопоточного программирования для таких ситуаций создаются специальные примитивы. В .NET эти примитивы называются Wait и Pulse-PulseAll и являются частью класса Monitor. Рисунок 10.8 поясняет ситуацию, которую мы собираемся запрограммировать.

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

Иллюстрированный самоучитель по Visual Basic .NET › Многопоточные приложения › Совместная работа с данными по мере их создания

Иллюстрированный самоучитель по Visual Basic .NET › Многопоточные приложения › Совместная работа с данными по мере их создания

Иллюстрированный самоучитель по Visual Basic .NET › Многопоточные приложения › Совместная работа с данными по мере их создания
Рис. 10.8. Проблема "поставщик/потребитель"

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.