Параллельные процессы (concurrent processes)

Страницы работы

Содержание работы

Лекция 3.

Параллельные процессы. (concurrent processes)

3.1.   Введение

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

Синхронизация - это использование специальных неделимых (атомарных) операций для кооперации между потоками.

Развитие вычислительной техники идет по пути увеличения производительности и уменьшения габаритных размеров. Уже существуют многопроцессорные комплексы, содержащие до 30 процессоров. Следовательно, появилась реальная возможность обрабатывать информацию действительно параллельно.

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

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

3.2.   Асинхронные процессы.

Зачем нужна синхронизация? Рассмотрим пример.

Person A                                      Person B

3:30   Look in fridge. Out of milk.

3:05   Leave for store.

3:10   Arrive at store.                           Look in fridge. Out of milk.

3:15   Buy milk.                                   Leave for store.

3:20   Arrive home, put milk away.     Arrive at store.

3:25                                                     Buy milk.

3:30                                                     Arrive home, put milk away.

Oh no!

Как избегать подобных ситуаций? Надо синхронизировать действия этих двух персон с целью недопущения выполнения действий над предметом (в данном случае, молоком).

Например, сделать так, что бы никогда более одного человека не ходило в магазин. Но, если необходимо, то кто-то должен покупать. Давайте попробуем предупреждать партнера о том, что вы пошли в магазин. То есть:

n оставить записку

n убрать записку по завершении покупки

n если оставлена записка, то нельзя покупать молоко

if (noMilk)

{

if(noNote)

{

leave Note;

buy milk;

remove note;

}

}

Всегда ли это будет работать? А вдруг произойдет переключение на другой процесс после проверки отсутствия молока и записки, но до того, как мы оставим предупреждающую записку? Тогда второй процесс может успеть пойти за молоком. Наш процесс продолжит выполнение с оставления еще одной записки и тоже пойдет за молоком. Есть предложение различать записки, оставляемые различными процессами. Проиграйте эту ситуацию сами, мы вернемся к ней на зачете.

3.2.1.  Взаимоисключение.

Рассмотрим систему, обслуживающую в режиме разделения времени много терминалов. Предположим, что пользователи заканчивают каждую строку, которую они вводят в машину, символом возврата каретки. Ведется учет общего количества строк, вводимых в машину. Естественно, что контроль за каждым терминалом осуществляется отдельным процессом. Каждый из них прибавляет 1 к глобальной разделяемой переменой NumberOfStrings. Давайте посмотрим, что произойдет, если два процесса попытаются одновременно обратиться к этой переменной. Предположим, что у каждого процесса есть собственная копия кода:

LOAD (NumberOfStrings);

NumberOfStrings = NumberOfStrings + 1;

STORE(NumberOfStrings);

Пусть в данный момент NumberOfStrings имеет значение 12345.

Предположим теперь, что первый процесс выполняет функции загрузки LOAD и увеличение переменной NumberOfStrings на единицу. После чего значение в аккумуляторе будет равно 12346. Затем этот процесс (виду истечения выделенного ему кванта времени) уступает процессор второму процессу. Пусть теперь второй процесс выполнит все три функции. Следовательно, состояние глобальной переменной в аккумуляторе равно 12346 (сначала прочитали 12345, увеличили на 1 и записали). Затем второй процесс возвращает управление первому, тот берет значение NumberOfStrings из аккумулятора и записывает его в глобальную переменную. Следовательно, в результате 12346, а должно быть 12347. 

Причем, приложив немного фантазии, даже на этих трех командах можно рассмотреть и другие ошибочные варианты.

Похожие материалы

Информация о работе