3121
Написание программы реализующей параллельную работу нескольких процессов
Курсовая
Информатика, кибернетика и программирование
Необходимо написать программу, реализующую параллельную работу нескольких процессов. Каждый процесс может состоять из одного или нескольких потоков. Любой из потоков, работающих в составе этих процессов, может быть приостановлен и вновь запущен неко...
Русский
2012-10-24
121.5 KB
25 чел.
Необходимо написать программу, реализующую параллельную работу нескольких процессов. Каждый процесс может состоять из одного или нескольких потоков. Любой из потоков, работающих в составе этих процессов, может быть приостановлен и вновь запущен некоторой определенной клавишей (можно использовать буквенные или цифровые клавиши). Нажатия клавиш обрабатывать с помощью прерывания от клавиатуры (по материалам лаб. работы №1).
Окончание работы программы должно происходить при приостановке всех потоков их ключевыми клавишами либо при нажатии клавиши ESC. При окончании работы необходимо выполнить корректное завершение, т.е. “дочитать” всю информацию из буфера каждого процесса (при его наличии), закрыть все открытые файлы и т.п. по материалам лаб. работы №4.
Те потоки, которые выводят информацию на экран, должны использовать для этого каждый свое отдельное окно, обрамленное рамкой экран визуально делится на несколько окон, в каждом из которых отображается один процесс.
Дополнительное информационное окно должно содержать описание управляющих клавиш и краткое сообщение о тех действиях, которые выполняются в программе: номер потока, его статус в текущий момент времени (активен, приостановлен, ожидает), другую информацию (указание величины выделенного потоку кванта времени, процент заполненности буфера и т.п.) в зависимости от конкретного потока.
Программа должна работать устойчиво, без “зависаний” и непредвиденных зрительных эффектов. В случае необходимости указания параметров при запуске программы необходимо предусмотреть и обработать все возможные ошибки (с выводом диагностики на экран).
Задачи 1, 3, 6 предполагают наличие управляющего блока, который, используя прерывания таймера, случайным образом определяет очередной активный поток и выделяет ему кванты времени (возможно, в рамках большего кванта, выделенного всему процессу). Кванты времени как для процесса в целом, так и для его потоков изначально задавать некоторой фиксированной величины, но предусмотреть возможность её изменения во время работы путем нажатия некоторых ключевых клавиш (для каждого из потоков предусмотреть свою клавишу) т.е. можно, например, увеличить или уменьшить квант только потока-пpоизводителя. При этом допустимы разные варианты реализации “общий” квант может либо меняться, либо оставаться постоянным (тогда при ускорении одного потока другой автоматически замедлится, т.к. величина его кванта уменьшится).
Потоки этого класса задач могут иметь три статуса: “активен”, “ожидает” или “приостановлен”. В процессе работы может возникнуть, например, следующая ситуация. Поток-потребитель приостановлен своей ключевой клавишей, следовательно, буфер не освобождается. Поток-производитель активен, он заполнит буфер информацией и перейдёт в состояние ожидания. Из этого состояния он сможет выйти только после того, как будет возобновлена (нажатием клавиши) работа потока-потребителя, который освободит место в буфере для помещения новой информации. В случае приостановки производителя возникнет аналогичная ситуация, только с пустым буфером. Приостановка/возобновление потока возможны в любом его состоянии как в активном, так и в состоянии ожидания.
Задачи 2, 4, 5, 7 должны выполняться равномерно, независимо от степени загрузки системы. Для этого каждой из них необходимо получать управление через фиксированное количество “тиков” системного таймера, во время которого они выполнят какое-то свое элементарное действие (“бегущая строка” или “летающий объект” сместится на одну позицию, сменится нота в музыке…). При такой реализации скорость каждого потока будет определяться количеством “тиков” таймера между его запусками. Для уменьшения скорости такого потока достаточно после нажатия ключевой клавиши предоставлять ему управление реже, через большее число “тиков”, соответственно для ускорения такого потока опять же после нажатия ключевой клавиши ему предоставляется управление чаще, в пределе на каждом “тике”. Так, “бегущая строка” должна двигаться равномерно с постоянной скоростью (если она не приостановлена ключевой клавишей) независимо от количества активных процессов в системе, музыка тоже играть равномерно… Потоки этого класса задач могут иметь два статуса: “активен” и “приостановлен”.
Задания:
3. Два потока: один выполняет поиск всех последовательных простых чисел и заносит их в буфер, второй осуществляет их вывод из буфера на экран (по материалам лаб. работы №4).
4. Вывод заголовка работы (фамилия и имя автора, название работы) постоянно меняющегося цвета. Место вывода (верхняя или нижняя строка), задавать в качестве параметра командной строки.
6. Два потока: один генерирует случайные числа и выбирает в буфер те, которые являются полным квадратом, второй выводит их из буфера на экран (по материалам лаб. раб. №4).
7. Движущийся объект (в простейшем случае, например, летающий и отражающийся от границ шарик). Движение может осуществляться свободно или при управлении с клавиатуры (по материалам лаб. работы №5).
Параметры командной строки.
Программа принимает один параметр положение заголовка (a вверху, b внизу).
Описание основных алгоритмов, используемых в программе.
Вывод заголовка и летающий квадрат реализованы как фоновые процессы. Изменяют свой вид эти объекты благодаря генератору случайных чисел.
Для генерации чисел, являющихся полными квадратами, используется генератор случайных чисел. После каждого занесения (и извлечения) числа из буфера обновляется показание уровня заполненности буфера на экране. На каждый поток отводится свой квант времени с помощью генератора случайных чисел.
Для поиска простых чисел используется следующий алгоритм. Берем число из переменной Num (изначально там записана единица) и прибавляем к нему единицу до тех пор, пока оно не станет простым. Для проверки на простоту числа используется отдельная булева функция PrimeNumber. Найденное число заносится в буфер. Проверка на наличие свободного места в буфере находится в начале процедуры, поэтому, если в буфере нет свободного места, то поток переходит в состояние ожидания и новых простых чисел не ищет. Любое простое число, помещенное в буфер, не превосходит константы MaxLongint. Поиск простых чисел продолжается до тех пор, пока не истечет время, отведенное на работу данного потока. Поток печати простых чисел проверяет буфер на пустоту и, если буфер не пуст, то извлекает первое число из буфера и выводит его на экран. Если буфер пуст, то поток переходит в режим ожидания.
Описание основных переменных, констант и типов.
В программе для фиксирования состояний (статусов) процессов и потоков определён следующий тип:
type Status = (Assigned, Wait, Suspended);
Константы.
Title текст заголовока;
TitleRefresh период смены цвета заголовка;
Buf1Len размер буфера первого процесса;
Buf2Len размер буфера второго процесса;
Delay1 задержка для первого процесса;
Delay2 задержка для второго процесса;
StrLen длина строки окна вывода;
Kill флаг завершения программы;
SquareRefresh период движения квадрата;
TPos положение заголовка.
Переменные.
OldTHandler, OldKHandler старые обработчики прерываний;
Scr массив для прямого доступа к видеопамяти;
T, T1, T2 счётчики времени таймер;
Thread состояния потоков;
Buf1 буфер первого процесса;
Buf2 буфер второго процесса;
Top1, Top2 вершины буферов;
Time дополнительные времена для потоков;
CurThread номер текущего активного потока;
X1, Y1, X2, Y2 координаты экрана для вывода сгенерированных чисел;
SX, SY координаты квадрата;
dx, dy «направляющие» квадрата;
tmp_symbol, tmp_attr перекрытая квадратом часть экрана;
Num полученное простое число.
Описание подпрограмм.
Print процедура вывода строки на экран;
Fly процедура сдвига летающего квадрата;
THandler обработчик прерываний таймера;
PrintStatus вывод на экран состояния заданного потока;
ChangeStatus изменение состояния заданного потока;
Prod1, Cons1, Prod2, Cons2 процедуры потоков потребителей и производителей;
PrimeNumber функция проверки числа на простоту;
KHandler обработчик прерываний клавиатуры;
SetCurSize процедура изменения размера курсора;
Initialize инициализирует основные переменные;
KillProc процедура завершения работы программы.
Работа программы (снимок экрана).
Исходный код программы.
program solution;
{$M $1024, 0, 0}
uses
Crt, Dos;
type
Status = (Active, Waits, Suspended); { Состояния потока }
const
Title = 'Заголовок'; { Текст заголовка }
TitleRefresh = 10; { Период смены цвета заголовка }
Buf1Len = 13; { Размер буфера первого процесса }
Buf2Len = 13; { Размер буфера второго процесса }
Delay1 = 10000; { Задержка для первого процесса }
Delay2 = 10000; { Задержка для второго процесса }
StrLen = 39; { Длина строки окна вывода }
Kill: Boolean = False; { Флаг завершения программы }
SquareRefresh = 2; { Период движения квадрата }
TPos: Byte = 1;
var
OldTHandler, OldKHandler: Procedure; { Старые обработчики прерываний }
Scr: Array[1..25, 1..80] of Record { Массив для прямого доступа к видеопамяти }
Symbol: Char;
Attr: Byte;
end Absolute $B800:$0000;
T, T1, T2: Word; { Счётчики времени таймера }
Thread: Array[1..6] of Status; { Состояния потоков }
Buf1: Array[1..Buf1Len] of Word; { Буфер первого процесса }
Buf2: Array[1..Buf2Len] of Longint; { Буфер второго процесса }
Top1, Top2: Word; { Вершины буферов }
Time: Array[1..4] of Byte; { Дополнительные времена для потоков }
CurThread: Byte; { Номер текущего активного потока }
X1, Y1, X2, Y2: Byte; { Координаты экрана для вывода сгенерированных чисел }
F: Text; { Файл с текстом }
SX, SY: Byte; { Координаты квадрата }
dx, dy: Integer; { "Направляющие" квадрата }
tmp_symbol: Array[0..1, 0..1] of Char; { Перекрытая квадратом часть экрана }
tmp_attr: Array[0..1, 0..1] of Byte;
Num: Longint;
{ Вывод строки S на экран начиная с i-го столбца, j-й строки цветом Color }
procedure Print(const S: String; const i, j: Byte; const Color: Byte);
var
k: Integer;
begin
if i + Length(S) - 1 > 80 then Exit;
for k := i to i + Length(S) - 1 do begin
Scr[j, k].Attr := Color;
Scr[j, k].Symbol := S[k - i + 1];
end;
end;
{ Сдвигает летающий квадрат }
procedure Fly;
var
i, j: Integer;
begin
while (SX + dx > 64) or (SX + dx < 45) or (SY + dy > 22) or (SY + dy < 3) do
begin
case Random(4) of
0: dx := -1;
1: dx := 1;
2: dx := 2;
3: dx := -2;
end;
case Random(4) of
0: dy := -1;
1: dy := 1;
2: dy := 2;
3: dy := -2;
end;
end;
for i := 0 to 1 do
for j := 0 to 1 do
begin
Scr[SY + j, SX + i].Attr := tmp_attr[j, i];
Scr[SY + j, SX + i].Symbol := tmp_symbol[j, i];
end;
SX := SX + dx;
SY := SY + dy;
for i := 0 to 1 do
for j := 0 to 1 do
begin
tmp_attr[j, i] := Scr[SY + j, SX + i].Attr;
tmp_symbol[j, i] := Scr[SY + j, SX + i].Symbol;
end;
for i := 0 to 1 do
for j := 0 to 1 do
begin
Scr[SY + j, SX + i].Attr := LightGreen;
Scr[SY + j, SX + i].Symbol := Chr(219);
end;
end;
{ Обработчик прерываний системного таймера }
{$F+}
procedure THandler; Interrupt;
begin
if Thread[1] = Active then begin
Inc(T1);
if T1 >= TitleRefresh then begin
Print(Title, 40 - Length(Title) div 2, TPos, 1 + Random(15));
T1 := 0;
end;
end;
if Thread[2] = Active then begin
Inc(T2);
if T2 >= SquareRefresh then begin
Fly;
T2 := 0;
end;
end;
Inc(T);
Inline($9C);
OldTHandler;
end;
{$F-}
{ Вывод на экран состояния i-го потока }
procedure PrintStatus(const i: Byte);
var
_Y: Byte;
begin
case Thread[i] of
Active: Print('Активен ', 66, 3 + i, LightGreen);
Waits: Print('Ожидание ', 66, 3 + i, Yellow);
Suspended: Print('Остановлен ', 66, 3 + i, LightRed);
end;
end;
{ Изменение состояния i-го потока }
procedure ChangeStatus(const i: Byte);
begin
case i of
1:
begin
if Thread[1] = Active then begin
Thread[1] := Suspended;
NoSound;
end
else
Thread[1] := Active;
PrintStatus(1);
end;
2:
begin
if Thread[2] = Active then Thread[2] := Suspended else Thread[2] := Active;
PrintStatus(2);
end;
3:
begin
if Thread[3] <> Suspended then
Thread[3] := Suspended
else
if CurThread = 0 then Thread[3] := Active else Thread[3] := Waits;
PrintStatus(3);
end;
4:
begin
if Thread[4] <> Suspended then
Thread[4] := Suspended
else
if CurThread = 1 then Thread[4] := Active else Thread[4] := Waits;
PrintStatus(4);
end;
5:
begin
if Thread[5] <> Suspended then
Thread[5] := Suspended
else
if CurThread = 2 then Thread[5] := Active else Thread[5] := Waits;
PrintStatus(5);
end;
6:
begin
if Thread[6] <> Suspended then
Thread[6] := Suspended
else
if CurThread = 3 then Thread[6] := Active else Thread[6] := Waits;
PrintStatus(6);
end;
end;
end;
{ Поток-производитель первого процесса (генерация чисел) }
procedure Prod1(const TMax: Byte);
var
Z: String[5];
Num: Word;
begin
if Thread[3] = Suspended then Exit;
if (Thread[3] = Waits) and (Top1 <> Buf1Len) then Thread[3] := Active;
if Thread[3] = Active then begin
Print(' ', 66, 11, White);
Str(TMax, Z);
Print(Z, 66, 11, White);
end;
PrintStatus(3);
T := 0;
while (T <= TMax + Time[1]) and (Thread[3] <> Suspended) do begin
if Top1 = Buf1Len then begin
Thread[3] := Waits;
PrintStatus(3);
Break;
end;
repeat
Num := Random(6000);
until Frac(Sqrt(Num)) < 1e-6;
Inc(Top1);
Buf1[Top1] := Num;
Str(Top1 / Buf1Len * 100:2:2, Z);
Print(Z + ' % ', 66, 16, White);
Delay(Delay1);
end;
if Thread[3] = Active then Print('Время вышло', 66, 6, LightGray);
Print(' - ', 66, 11, White);
end;
{ Поток-потребитель первого процесса }
procedure Cons1(const TMax: Byte);
var
i, j: Integer;
S: String;
begin
if Thread[4] = Suspended then Exit;
if (Thread[4] = Waits) and (Top1 <> 0) then Thread[4] := Active;
if Thread[4] = Active then begin
Print(' ', 66, 12, White);
Str(TMax, S);
Print(S, 66, 12, White);
end;
PrintStatus(4);
T := 0;
while (T <= TMax + Time[2]) and (Thread[4] <> Suspended) do begin
if Top1 = 0 then begin
Thread[4] := Waits;
PrintStatus(4);
Break;
end;
Str(Buf1[1]: 4, S);
if X1 + Length(S) > StrLen then begin
X1 := 0;
if Y1 = 8 then begin
for i := 3 to 10 do
for j := 3 to 41 do
Scr[i, j].Symbol := Scr[i + 1, j].Symbol;
for j := 3 to 41 do
Scr[11, j].Symbol := ' ';
end
else Inc(Y1);
end;
Print(S, 3 + X1, 3 + Y1, White);
Inc(X1, Length(S) + 2);
Dec(Top1);
for i := 1 to Top1 do
Buf1[i] := Buf1[i + 1];
Str(Top1 / Buf1Len * 100:2:2, S);
Print(S + ' % ', 66, 16, White);
Delay(Delay1);
end;
if Thread[4] = Active then Print('Время вышло', 66, 7, LightGray);
Print(' - ', 66, 12, White);
end;
{ Возвращает True, если число x - простое }
function PrimeNumber(const x: Longint): Boolean;
var
i: Integer;
u: Longint;
begin
PrimeNumber := False;
if x <= 1 then Exit;
for i := 2 to Trunc(Sqrt(x)) do
if x mod i = 0 then Exit;
PrimeNumber := True;
end;
{ Поток-производитель второго процесса (текс из файла) }
procedure Prod2(const TMax: Byte);
var
i: Integer;
c: Char;
Z: String[8];
begin
if Thread[5] = Suspended then Exit;
if (Thread[5] = Waits) and (Top2 <> Buf2Len) then Thread[5] := Active;
if Thread[5] = Active then begin
Print(' ', 66, 13, White);
Str(TMax, Z);
Print(Z, 66, 13, White);
end;
PrintStatus(5);
T := 0;
while (T <= TMax + Time[3]) and (Thread[5] <> Suspended) do begin
if Top2 = Buf2Len then begin
Thread[5] := Waits;
PrintStatus(5);
Break;
end;
repeat
Inc(Num);
until PrimeNumber(Num) or (Num = MaxLongint);
if Num = MaxLongint then Num := 2;
Inc(Top2);
Buf2[Top2] := Num;
Str(Top2 / Buf2Len * 100:2:2, Z);
Print(Z + ' % ', 66, 17, White);
Delay(Delay2);
end;
if Thread[5] = Active then Print('Время вышло' , 66, 8, LightGray);
Print(' - ', 66, 13, White);
end;
{ Поток-потребитель второго процесса }
procedure Cons2(const TMax: Byte);
var
i, j: Integer;
Z: String[8];
S: String;
begin
if Thread[6] = Suspended then Exit;
if (Thread[6] = Waits) and (Top2 <> 0) then Thread[6] := Active;
if Thread[6] = Active then begin
Print(' ', 66, 14, White);
Str(TMax, Z);
Print(Z, 66, 14, White);
end;
PrintStatus(6);
T := 0;
while (T <= TMax + Time[4]) and (Thread[6] <> Suspended) do begin
if Top2 = 0 then begin
Thread[6] := Waits;
PrintStatus(6);
Break;
end;
Str(Buf2[1]:10, S);
if X2 + Length(S) > StrLen then begin
X2 := 0;
if Y2 = 10 then begin
for i := 13 to 22 do
for j := 3 to 41 do
Scr[i, j].Symbol := Scr[i + 1, j].Symbol;
for j := 3 to 41 do
Scr[23, j].Symbol := ' ';
end
else Inc(Y2);
end;
Print(S, 3 + X2, 13 + Y2, White);
Inc(X2, Length(S) + 2);
Dec(Top2);
for i := 1 to Top2 do
Buf2[i] := Buf2[i + 1];
Str(Top2 / Buf2Len * 100:2:2, Z);
Print(Z + ' % ', 66, 17, White);
Delay(Delay2);
end;
if Thread[6] = Active then Print('Время вышло', 66, 8, LightGray);
Print(' - ', 66, 14, White);
end;
{ Обработчик прерываний клавиатуры }
{$F+}
procedure KHandler; Interrupt;
var
Local_Time: String[5];
begin
case Port[$60] of
1: Kill := True; { нажата Esc }
2: if Time[1] > 0 then Dec(Time[1]); { нажата 1 }
3: if Time[1] < 90 then Inc(Time[1]); { 2 }
4: if Time[2] > 0 then Dec(Time[2]); { 3 }
5: if Time[2] < 90 then Inc(Time[2]); { 4 }
6: if Time[3] > 0 then Dec(Time[3]); { 5 }
7: if Time[3] < 90 then Inc(Time[3]); { 6 }
8: if Time[4] > 0 then Dec(Time[4]); { 7 }
9: if Time[4] < 90 then Inc(Time[4]); { 8 }
59: ChangeStatus(1); { нажата F1 }
60: ChangeStatus(2); { F2 }
61: ChangeStatus(3); { F3 }
62: ChangeStatus(4); { F4 }
63: ChangeStatus(5); { F5 }
64: ChangeStatus(6); { F6 }
end;
Print(' ', 69, 11, White);
Print(' ', 69, 12, White);
Print(' ', 69, 13, White);
Print(' ', 69, 14, White);
Str(Time[1], Local_Time);
Print(' + ' + Local_Time, 69, 11, White);
Str(Time[2], Local_Time);
Print(' + ' + Local_Time, 69, 12, White);
Str(Time[3], Local_Time);
Print(' + ' + Local_Time, 69, 13, White);
Str(Time[4], Local_Time);
Print(' + ' + Local_Time, 69, 14, White);
Inline($9C);
OldKHandler;
end;
{$F-}
{ Изменение размера курсора }
procedure SetCurSize(const BegLine, EndLine: Byte);
var
Regs: Registers;
begin
with Regs do begin
AH := $01;
CH := BegLine;
CL := EndLine;
end;
Intr($10, Regs);
end;
{ Инициализация основных переменных }
procedure Initialize;
var
i, j: Integer;
begin
T1 := 0;
T2 := 0;
Top1 := 0;
Top2 := 0;
SetCurSize($20, $00);
for i := 1 to 6 do
Thread[i] := Active;
for i := 1 to 4 do
Time[i] := 0;
PrintStatus(1);
PrintStatus(2);
Print('Не запущен', 66, 6, LightGray);
Print('Не запущен', 66, 7, LightGray);
Print('Не запущен', 66, 8, LightGray);
Print('Не запущен', 66, 9, LightGray);
Print('0.00 %', 66, 16, White);
Print('0.00 %', 66, 17, White);
Print(' + 0', 66, 11, White);
Print(' + 0', 66, 12, White);
Print(' + 0', 66, 13, White);
Print(' + 0', 66, 14, White);
X1 := 0;
Y1 := 0;
X2 := 0;
Y2 := 0;
Num := 1;
dx := -1;
dy := 1;
SX := 50;
SY := 3;
for i := 0 to 1 do
for j := 0 to 1 do begin
tmp_attr[j, i] := Scr[SY + j, SX + i].Attr;
tmp_symbol[j, i] := Scr[SY + j, SX + i].Symbol;
end;
GetIntVec($9, @OldKHandler);
SetIntVec($9, Addr(KHandler));
GetIntVec($8, @OldTHandler);
SetIntVec($8, Addr(THandler));
end;
{ Действия при завершении работы программы }
procedure KillProc;
begin
Thread[3] := Suspended;
Thread[4] := Active;
Thread[5] := Suspended;
Thread[6] := Active;
T := High(T);
CurThread := 1;
while (Top1 <> 0) or (Top2 <> 0) do begin
T := 0;
case Random(2) of
0: Cons1(1 + Random(10));
1: Cons2(1 + Random(10));
end;
end;
SetIntVec($9, Addr(OldKHandler));
SetIntVec($8, Addr(OldTHandler));
Window(1, 1, 80, 25);
GotoXY(1, 25);
SetCurSize($06, $07);
Halt(0);
end;
var
v: String;
begin
v := ParamStr(1);
if (ParamCount = 0) or not ((Upcase(v[1]) = 'A') or (Upcase(v[1]) = 'B')) then begin
WriteLn('Неправильно задано положение заголовка.');
WriteLn('Формат:');
WriteLn('имя_файла Pos');
WriteLn('где Pos - положение заголовка (a - вверху, b - внизу).');
ReadLn;
Halt;
end;
if Upcase(v[1]) = 'B' then TPos := 25;
TextBackground(Black);
ClrScr;
Window(2, 2, 42, 24);
TextBackground(White);
ClrScr;
TextColor(Black);
GotoXY(17, 1);
Write('Процесс 1');
Window(3, 3, 41, 23);
TextBackground(Black);
ClrScr;
Window(2, 12, 42, 12);
TextBackground(White);
ClrScr;
TextColor(Black);
GotoXY(17, 1);
Write('Процесс 2');
Window(44, 2, 79, 24);
TextBackground(White);
ClrScr;
GotoXY(14, 1);
Write('Управление');
Window(45, 3, 78, 23);
TextBackground(Black);
ClrScr;
Window(45, 3, 78, 3);
TextBackground(3);
ClrScr;
TextColor(White);
GotoXY(8, 1);
Write('Изменение состояний');
Window(45, 4, 78, 9);
TextBackground(Black);
ClrScr;
TextColor(White);
WriteLn('F1 Заголовок :');
WriteLn('F2 Летающий квадрат:');
WriteLn('F3 Производитель 1 :');
WriteLn('F4 Потребитель 1 :');
WriteLn('F5 Производитель 2 :');
Write('F6 Потребитель 2 :');
Window(45, 10, 78, 10);
TextBackground(3);
ClrScr;
GotoXY(4, 1);
Write('Время <уменьшить>/<добавить>');
Window(45, 11, 78, 14);
TextBackground(Black);
ClrScr;
WriteLn('1/2 Производитель 1:');
WriteLn('3/4 Потребитель 1:');
WriteLn('5/6 Производитель 2:');
Write('7/8 Потребитель 2:');
Window(45, 15, 78, 15);
TextBackground(3);
ClrScr;
GotoXY(7, 1);
Write('Статистические данные');
Window(45, 16, 78, 17);
TextBackground(Black);
ClrScr;
WriteLn('Буфер 1 заполнен на:');
Write('Буфер 2 заполнен на:');
Window(45, 18, 78, 18);
TextBackground(3);
ClrScr;
Window(45, 19, 78, 23);
TextBackground(Black);
ClrScr;
GotoXY(1, 5);
Write('Esc - выход');
Initialize;
Randomize;
while True do begin
if Kill then KillProc;
CurThread := Random(4);
case CurThread of
0: Prod1(10 + Random(10));
1: Cons1(10 + Random(10));
2: Prod2(10 + Random(10));
3: Cons2(10 + Random(10));
end;
end;
end.
А также другие работы, которые могут Вас заинтересовать | |||
19343. | АРХИТЕКТУРЫ С ПОЛНЫМ И СОКРАЩЁННЫМ НАБОРОМ КОМАНД | 158.5 KB | |
АК ЛЕКЦИЯ № 20 АРХИТЕКТУРЫ С ПОЛНЫМ И СОКРАЩЁННЫМ НАБОРОМ КОМАНД Современная технология программирования ориентирована на языки высокого уровня ЯВУ главная задача которых облегчить процесс написания программ. Более 90 всего процесса программирования осуществл... | |||
19344. | КОНВЕЙЕРНАЯ АРХИТЕКТУРА | 146 KB | |
АК ЛЕКЦИЯ № 21 КОНВЕЙЕРНАЯ АРХИТЕКТУРА Конвейерная обработка данных. Что необходимо для сложения двух вещественных чисел представленных в форме с плавающей запятой Целое множество мелких операций таких как сравнение порядков выравнивание порядков сложение ман | |||
19345. | СУПЕРСКАЛЯРНЫЕ ПРОЦЕССОРЫ | 306.5 KB | |
АК ЛЕКЦИЯ № 22 СУПЕРСКАЛЯРНЫЕ ПРОЦЕССОРЫ Суперскалярные процессоры Поскольку возможности по совершенствованию элементной базы уже практически исчерпаны дальнейшее повышение производительности ВМ лежит в плоскости архитектурных решений. Как уже отмечалось од | |||
19346. | VLIW – ПРОЦЕССОРЫ. НЕТРАДИЦИОННЫЕ АРХИТЕКТУРЫ | 354 KB | |
АК ЛЕКЦИЯ № 23 VLIW ПРОЦЕССОРЫ. Нетрадиционные архитектуры Вычислительные системы с командными словами сверхбольшой длины VLIW Архитектура с командными словами сверхбольшой длины или со сверхдлинными командами VLIW Very Long Instruction Word известна с начала 80х из ряда универ... | |||
19347. | МНОГОЯДЕРНАЯ АРХИТЕКТУРА | 277 KB | |
АК ЛЕКЦИЯ № 24 МНОГОЯДЕРНАЯ АРХИТЕКТУРА Вычислительные системы класса MIMD Технология SIMD исторически стала осваиваться раньше что и предопределило широкое распространение SIMDсистем. В настоящее время тем не менее наметился устойчивый интерес к архитектурам класс... | |||
19349. | Проводниковые материалы | 88 KB | |
Лекция №2 Проводниковые материалы. Основные электрические параметры металлов Из общего курса физики известно что плотность электрического тока в веществе определяется зарядом q концентрацией n и дрейфовой средней направленной скоростью носителей заря | |||
19350. | Материалы используемые в электронных приборах | 126 KB | |
Лекция №1 Введение Для создания электронных приборов необходимо много различных материалов и уникальных технологических процессов. Современная радиотехника и особенно высокочастотная техника радиосвязь приборы и аппаратура радиоэлектроники требуют б... | |||
19351. | Неметаллические проводниковые материалы | 27.87 KB | |
Лекция №3. Неметаллические проводниковые материалы. Сверхпроводники. При понижении температуры удельное сопротивление p металлов уменьшается. Представляет большой интерес электропроводность металлов при весьма низких криогенных температурах приближающихся к... | |||