2

助けと洞察力が必要です。これは 3 つのタスクを持つ Ada-2005 のプログラムです。出力は「z」です。3 つのタスクがプログラム内の配置順に発生しない場合、出力は z = 2、z = 1 から z = 0 まで変化する可能性があります (これはプログラムで簡単に確認できます。出力を確認するために相互排除が試行されます。は z = 2)。

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;

私は最初にこのプログラムを試しました

(a) プラグマなしの場合、結果: 100 回の試行で、2: 86 の発生、1: 10 の発生、0: 4 の発生。

それで

(b) プラグマを使用した場合の結果: 100 回の試行で、2: 84 の発生、1: 14 の発生、0: 2 の発生。

2 つの結果がほぼ同じであるため、これは予想外です。これは、出力が同じ動作をするプラグマまたはプラグマがないことを意味します。

Ada の同時実行の達人である方は、このトピックに光を当ててください。セマフォを使用した代替ソリューション (可能であれば) も招待されます。

さらに、クリティカル プロセス (これは Ada で行うことです) についての私の意見では、プラグマを使用すると、結果は常に z = 2、100% になるはずです。(エイダではそうではないはずです)

4

3 に答える 3

5

3 つの操作を行う保護オブジェクトは、次のようになります。ただし、これが行うことは、3 つの変数 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;

一方、3 つのタスクが適切な順序で「結果を送信」することを確認するには、P を書き直して、Update_X が呼び出されるまで Update_Y の呼び出しがブロックされるようにすることができます。関数ではなく出力パラメーター。

  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;

3 つのタスクには、任意の優先度を設定できます。ただし、Update_Z を呼び出すタスクは、他の 2 つが報告するまでブロックされます。

于 2010-03-22T21:00:31.273 に答える
1

これらのプラグマは、システム上のタスクに優先順位を付けるだけであり、それらの変数に対する相互排除を保証するものではありません。

それで十分なシステムもあるかもしれません。ただし、最近のほとんどの Ada 実装は Ada タスクを OS スレッドにマップしており、最近のコンシューマ PC のほとんどは複数のプロセッサを搭載しており、プロセッサ間でスレッドをスピルすることができます。最も優先度の高いスレッドの実行中に、OS が 2 番目のプロセッサで次に優先度の低いスレッドをスケジュールするのを止めるものは何もありません。

プログラム内でのこの種の動作は、「競合状態」と呼ばれます。

これらの変数の相互排除が必要な場合は、それを実装する必要があります。変数の制御を 1 つのタスクに渡し、ランデブーを使用して他のタスクからそれらを変更するか、それらを保護されたオブジェクトに入れることを検討してください。ランデブーを正しく行うのははるかに難しいため、後者をお勧めします。ただし、呼び出しを特定の方法で順序付けしたい場合は、他のタスクでランデブーを呼び出すマスター コントローラー タスクが適している場合があります。

于 2010-03-23T13:51:57.253 に答える
0

これは、上記のシーケンシャル バリアントであるプログラムです。.... 1 つのタスクだけで (Marc C と TED によって提案されているように、1 つの手順を使用すれば回避できます)

WITH Ada.Text_IO; Ada.Text_IO を使用します。

WITH Ada.Integer_Text_IO; USE Ada.Integer_Text_IO;

システムと; 使用システム;

手続き xyzsimple は

x : 整数 := 0; y : 整数 := 0; z : 整数 := 0;

タスク タイプ xyz;

T:xyz;

タスク本体 xyz は

始める

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

xyz を終了します。

Put(" z = "); を開始します。

置く(z);

xyzsimple を終了します。

このプログラムは常に出力 z = 2 を生成しますが、それでは私が何をしようとしているのかを説明するのに役立ちません。このプログラムは、並行性のパラダイムではなく、決定論的です! また、この番組では、TED が言及した「RACE CONDITION」が表示されることはありません。

于 2010-03-25T03:15:29.230 に答える