2010-03-22 3 views
2

Мне нужна помощь, а также некоторое понимание. Это программа в Ada-2005, которая имеет 3 задачи. Выходной сигнал равен «z». Если 3 задачи не выполняются в порядке их размещения в программе, тогда вывод может варьироваться от z = 2, z = 1 до z = 0 (это легко увидеть в программе, взаимное исключение пытается сделать вывод z = 2).Проблемы в Ada Concurrency

WITH Ada.Text_IO; USE Ada.Text_IO; 
WITH Ada.Integer_Text_IO; USE Ada.Integer_Text_IO; 
WITH System; USE System; 

procedure xyz is 
    x : Integer := 0; 
    y : Integer := 0; 
    z : Integer := 0; 

    task task1 is 
     pragma Priority(System.Default_Priority + 3); 
    end task1; 

    task task2 is 
     pragma Priority(System.Default_Priority + 2); 
    end task2; 

    task task3 is 
     pragma Priority(System.Default_Priority + 1); 
    end task3; 

    task body task1 is 
    begin 
     x := x + 1; 
    end task1; 

    task body task2 is 
    begin 
     y := x + y; 
    end task2; 

    task body task3 is 
    begin 
     z := x + y + z; 
    end task3; 

begin 
    Put(" z = "); 
    Put(z); 
end xyz; 

я впервые попробовал эту программу

(а) без прагм, результат: В 100 попыток, вхождение 2: 86, 1 совпадения: 10, вхождение 0: 4.

Тогда

(б) с прагм, результат: В 100 попыток, вхождение 2: 84, 1 совпадения: 14, вхождение 0: 2.

Который является неожиданным, так как 2 результатов, близких идент скую. Что означает прагмы, или нет прагм, результат имеет такое же поведение.

Те, кто являются консультантами по аду, могут пролить свет на эту тему. Также предлагаются альтернативные решения с семафорами (если возможно).

Далее, на мой взгляд, для критического процесса (это то, что мы делаем с Ada), с прагмами результат должен быть z = 2, 100% в любое время, следовательно, или иначе эта программа должна называться 85% критической !!!! (Это не должно быть так с Ada)

+0

@ Boris Pavlovic: Спасибо! .... Я боролся с форматированием кода! ... – Arkapravo

+0

Дополнительная информация необходима. Какой компилятор? Какая операционная система? Какой процессор, он многоядерный? Несколько задач могут выполняться одновременно, поэтому, если для выполнения доступны два или более ядра ЦП, могут выполняться две или более задачи (если есть необходимая поддержка компилятора и ОС), независимо от того, имеет ли более высокий приоритет. –

+1

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

ответ

5

Защищенный объект для выполнения трех операций может выглядеть примерно так. Но учтите, что все это делается, чтобы убедиться, что три переменные x, y и z соответствуют порядку, в котором произошли обновления; он ничего не говорит о порядке.

protected P is 
     procedure Update_X; 
     procedure Update_Y; 
     procedure Update_Z; 
     function Get_Z return Integer; 
    private 
     X : Integer := 0; 
     Y : Integer := 0; 
     Z : Integer := 0; 
    end P; 
    protected body P is 
     procedure Update_X is 
     begin 
     X := X + 1; 
     end Update_X; 
     procedure Update_Y is 
     begin 
     Y := Y + X; 
     end Update_Y; 
     procedure Update_Z is 
     begin 
     Z := X + Y + Z; 
     end Update_Z; 
     function Get_Z return Integer is 
     begin 
     return Z; 
     end Get_Z; 
    end P; 

С другой стороны, чтобы убедиться, что все три задачи «представить свои результаты» в правильном порядке, вы могли бы переписать P так, что вызов сказать Update_Y будет блокировать до тех пор, Update_X не было названо: Get_Z Сейчас должна быть запись с параметром out, а не функцией.

protected P is 
     entry Update_X; 
     entry Update_Y; 
     entry Update_Z; 
     entry Get_Z (Result : out Integer); 
    private 
     X_Updated : Boolean := False; 
     Y_Updated : Boolean := False; 
     Z_Updated : Boolean := False; 
     X : Integer := 0; 
     Y : Integer := 0; 
     Z : Integer := 0; 
    end P; 
    protected body P is 
     entry Update_X when True is 
     begin 
     X := X + 1; 
     X_Updated := True; 
     end Update_X; 
     entry Update_Y when X_Updated is 
     begin 
     Y := Y + X; 
     Y_Updated := True; 
     end Update_Y; 
     entry Update_Z when Y_Updated is 
     begin 
     Z := X + Y + Z; 
     Z_Updated := True; 
     end Update_Z; 
     entry Get_Z (Result : out Integer) when Z_Updated is 
     begin 
     Result := Z; 
     end Get_Z; 
    end P; 

Эти три задачи теперь могут иметь любой приоритет, который вам нравится. Но задача, которая вызывает Update_Z, будет блокироваться до тех пор, пока не будут сообщены остальные два.

+0

Большое спасибо! ..... так, как мы определяем порядок? это с прагмами? – Arkapravo

+0

Как вы делаете «Защищенный» ..... используя семафоры/мьютексы ??? – Arkapravo

+0

Ну, я не «делаю» «защищенный», компилятор Ada делает это, используя то, что подходит для соответствующей системы. Например, в Ada RTS есть процедура Unlock, которая в Windows использует LeaveCriticalSection(), но на VxWorks используется semGive(). Что касается заказа, я думаю, это зависит от того, почему вы хотите, чтобы эти три вещи происходили один за другим. Самый простой способ - не использовать задачи в первую очередь! Но если вы хотите (скажем), чтобы три задачи выполнялись параллельно, а затем синхронизировались в порядке, вам нужно было бы использовать записи в защищаемом объекте. Обновит мой ответ позже. –

1

Ну, эти прагмы просто определяют приоритеты задач в вашей системе, они не гарантируют какого-либо взаимного исключения этих переменных.

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

Такое поведение в программе называется «условием гонки».

Если вы хотите взаимное исключение из этих переменных, вам необходимо реализовать это. Либо давайте управление переменными одной задаче и используйте рандеву, чтобы изменить их из других задач, либо взгляните на их включение в protected objects. Я бы предложил последнее, так как рандеву можно было бы намного сложнее добиться. Однако, если вы хотите заказать вызовы определенным образом, задача мастера, вызывающая рандеву на другие задачи, может быть способом.

+0

@ T.E.D: Спасибо! ... Я еще раз подумаю о программе ... Думаю, нам нужно больше обсуждать параллелизм, для этого предназначена Ада! ... Ада без параллелизма больше Паскаль-иш! ... – Arkapravo

+0

@ TED: Я пытался «защитить» каждую отдельную задачу с помощью семафоров .... и сохранил тот же порядок прагмы ..... однако ничего, похоже, не изменилось ... Можете ли вы мне помочь? и написать параллельный код, который правильно заказывает задачи, таким образом, решение «гоночной проблемы»! ... большое спасибо ... – Arkapravo

+0

@ T.E.D: Возможно, вы также захотите принять участие в обсуждении (выше на этой странице), где я, похоже, нарисовал флешку для использования задач! :) – Arkapravo

0

вот программа, которая является последовательным вариантом вышеизложенного! .... только с одной задачей (даже этого можно избежать, если я использую одну процедуру, как предложено Marc C и T.E.D)

С Ada.Text_IO; ИСПОЛЬЗОВАТЬ Ada.Text_IO;

С Ada.Integer_Text_IO; USE Ada.Integer_Text_IO;

С системой; USE System;

процедура xyzsimple является

х: Целое число: = 0; y: Целое число: = 0; z: Целое число: = 0;

тип задачи xyz;

T: xyz;

тело Задачи хуг является

начинает

х: = х + 1;
y: = x + y;
z: = x + y + z;

конец xyz;

begin Put ("z =");

Put (z);

конец xyzsimple;

Эта программа всегда выдает выход z = 2, но тогда это не служит для иллюстрации того, что я пытался сделать. Эта программа детерминирована, а не парадигма параллелизма! Кроме того, эта программа никогда не представит «СОСТОЯНИЕ РАССТОЯНИЯ», о котором упоминал T.E.D.