Это переменные, показывающие, что произошли
Это переменные, показывающие, что произошли определенные события.
Для объявления события служит оператор POST(имя переменной), для ожидания события - WAIT (имя переменной). Для чистки (присваивания нулевого значения) - оператор CLEAR(имя переменной).
Варианты реализации - не хранящие информацию (по оператору POST из ожидания выводятся только те процессы, которые уже выдали WAIT) , однократно объявляемые (нет оператора чистки).
Метод последовательной верхней релаксации (SOR) с использованием массива событий.
float A[ L1 ][ L2 ];
struct event s[ L1 ][ L2 ];
for ( i = 0; i < L1; i++)
for ( j = 0; j < L2; j++) { clear( s[ i ][ j ]) };
for ( j = 0; j < L2; j++) { post( s[ 0 ][ j ]) };
for ( i = 0; i < L1; i++) { post(
s[ i ][ 0 ]) };
..............
..............
parfor ( i = 1; i < L1-1; i++)
parfor ( j = 1; j < L2-1; j++)
{ wait( s[ i-1 ][ j ]);
wait( s[ i ][ j-1 ]);
A[ i ][ j ] = (A[ i-1 ][ j ] + A[ i+1][ j ] + A[ i ][ j-1 ] + A[ i ][ j+1 ]) / 4;
post( s[ i ][ j ]);
}
Обмен сообщениями (message passing)
Хоар (Xoare) 1978 год, "Взаимодействующие параллельные процессы". Цели - избавиться от проблем разделения памяти и предложить модель взаимодействия процессов для распределенных систем.
send (destination, &message, msize);
receive ([source], &message, msize);
Адресат - процесс. Отправитель - может не специфицироваться (любой).
С буферизацией (почтовые ящики) или нет (рандеву - Ада, Оккам).
Пайпы ОС UNIX - почтовые ящики, заменяют файлы и не хранят границы сообщений (все сообщения объединяются в одно большое, которое можно читать произвольными порциями.
Пример использования буферизуемых сообщений.
#define N 100 /* максимальное число сообщений */
/* в буфере*/
#define msize 4 /* размер сообщения*/
typedef int message[msize];
producer()
{
message m;
int item;
while (TRUE)
{
produce_item(&item);
receive(consumer, &m, msize); /* получает пустой */
/* "контейнер" */
build_message(&m, item); /* формирует сообщение */
send(consumer, &m, msize);
}
}
consumer()
{
message m;
int item, i;
for (i = 0; i < N; i ++)
send (producer, &m, msize); /* посылает все пустые *.
/* "контейнеры" */
while (TRUE)
{
receive(producer, &m, msize);
extract_item(&m, item);
send(producer, &m, msize); /* возвращает "контейнер" */
consume_item(item);
}
}
producer() AND consumer() /* запустили 2 процесса */
Механизмы семафоров и обмена сообщениями взаимозаменяемы семантически и на мультипроцессорах могут быть реализованы один через другой. Другие классические задачи взаимодействия процессов - проблема обедающих философов (Dijkstra) и "читатели-писатели".
Содержание раздела